알고리즘 과 데이터 구조 - 가방 문제
제목.
N 개의 아 이 템 과 M 용량 의 가방 이 있 으 며, 각 아 이 템 은 1 개 만 찾 을 수 있다.제 i 물품 의 비용 은 c [i] 이 고 가 치 는 v [i] 입 니 다.어떤 물건 을 가방 에 넣 으 면 가 치 를 총화 할 수 있 는 지 알 아 보 세 요.
분석 하 다.
이것 은 가장 기본 적 인 가방 문제 로 모든 아 이 템 이 하나 밖 에 없 으 므 로 놓 거나 놓 지 않 는 것 을 선택 할 수 있 는 것 이 특징 이다.하위 문제 로 상 태 를 정의 합 니 다: 즉 f [i] [j] 는 앞의 i 개 아 이 템 을 j 용량 의 가방 에 넣 으 면 얻 을 수 있 는 최대 가 치 를 표시 합 니 다.그 상태 전이 방정식 은 다음 과 같다.
f[i][j]=max{f[i-1][j],f[i-1][j-c[i]]+v[i]}
f[j] i j 。
j-c[i]<j , j=0……M f[j], f[j] i f[j-c[i]], i-1 f[j-c[i]]。
, j=M……0 f[j], f[j] f[j-c[i]] f[i-1][j-c[i]] 。
/*
* n:
* capacity:
* c[i]: i cost
* v[i]: i value
* f[j]:i j
*/
int getMaxValue(int n,int capacity){
for(int i=0;i<n;i++)
for(int j=capacity;j>=0;j--)
if(i==0){
if(j>=c[i])f[j]=v[i];
else f[j]=0;
}
else if(j>=c[i])f[j]=max(f[j],f[j-c[i]]+v[i]);
return f[capacity];
}
N M , 。 i c[i], v[i]。 。
01 , , 0 、 1 、 2 ……。 01 , f[i][j] i j 。 :
f[i][j]=max{ f[i-1][j-k*c[i]]+k*v[i] | 0<=k*c[i]<=M }
i、j c[i]<=c[j] w[i]>=w[j], j , 。
M , , 。
01
: i M/c[i] , i M/c[i] , 01 。 , 01 : 。
: i c[i]*2^k、 v[i]*2^k , k c[i]*2^k<=M。 , i , 2^k 。 O(logM/c[i]) , 。
O(MN) : 01 j=M..0 。 i f[i][j] f[i-1][j-c[i]] 。 , , “ i ” , i f[i-1][j-c[i]]。 , “ i ” , i f[i][j-c[i]], j=0..M 。
/*
* n:
* capacity:
* c[i]: i cost
* v[i]: i value
* f[j]:i j
*/
int getMaxValue(int n,int capacity){
for(int i=0;i<n;i++)
for(int j=0;j<=capacity;j++)
if(i==0){
if(j>=c[i])f[j]=v[i]*(j/c[i]);
else f[j]=0;
}
else if(j>=c[i])f[j]=max(f[j],f[j-c[i]]+v[i]);
return f[capacity];
}
N M , i n[i] 。 i c[i], v[i]。 。
。 , i n[i]+1 : 0 , 1 …… n[i] 。 f[i][v] i v , :
f[i][j]=max{ f[i-1][j-k*c[i]]+k*v[i] | 0<=k<=n[i] }
i , , 。 1,2,4,...,2^(k-1),n[i]-2^k+1, k n[i]-2^k+1>0 。 , n[i] 13, 1,2,4,6 。
n[i], n[i] i 。
/**
* : i (i )
* cost:i c[i]
* weight:i v[i]
* amount:i n[i]
* CompletePack:
* ZeroOnePack:01
*/
void MultiplePack(cost,weight,amount){
if(cost*amount>=capacity){
CompletePack(cost,weight);return;
}
int k=1;
while(k<amount){
ZeroOnePack(k*cost,k*weight);
amount=amount-k;
k=k*2;
}
ZeroOnePack(amount*cost,amount*weight);
}
:
ZOJ Problem Set - 1149 Dividing
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=149
:
1、2、3、4、5、6 6 ( ⊙﹏⊙b ), , , , 。
:
, cost , 。
:
#include <iostream>
#define MAX 210002
#define max(a,b) (a)>(b)?(a):(b)
using namespace std;
long nums[6],total,f[MAX];
int input(){
for(int i=total=0;i<6;i++){
cin>>nums[i];
total+=nums[i]*(i+1);
}
if(total)return 1;
return 0;
}
void zeroOnePack(int cost,int value,long capacity){
for(int j=capacity;j>-1;j--)
if(j>=cost)f[j]=max(f[j],f[j-cost]+value);
}
void completePack(int cost,int value,long capacity){
for(int j=0;j<=capacity;j++)
if(j>=cost)f[j]=max(f[j],f[j-cost]+value);
}
void multiplePack(int cost,int value,int count,long capacity){
if(cost*count>=capacity){
completePack(cost,value,capacity);
return;
}
int k=1;
while(k<count){
zeroOnePack(cost*k,value*k,capacity);
count-=k;
k*=2;
}
zeroOnePack(cost*count,value*count,capacity);
}
int judge(long capacity){
for(int i=0;i<6;i++){
if(i==0){
for(int j=0;j<=capacity;j++)
if(j<i+1)f[j]=0;
else{
int amount=j/(i+1);
f[j]=(nums[i]>=amount ? (i+1)*amount : nums[i]*(i+1));
}
}
else multiplePack(i+1,i+1,nums[i],capacity);
}
if(f[capacity]==capacity)return 1;
return 0;
}
int main()
{
int T=1;
while(input()){
printf("Collection #%d:
",T++);
if(total&1)cout<<"Can't be divided."<<endl<<endl;
else if(judge(total/2))cout<<"Can be divided."<<endl<<endl;
else cout<<"Can't be divided."<<endl<<endl;
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
정수 반전Udemy 에서 공부 한 것을 중얼거린다 Chapter3【Integer Reversal】 (예) 문자열로 숫자를 반전 (toString, split, reverse, join) 인수의 수치 (n)가 0보다 위 또는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.