알고리즘 과 데이터 구조 - 가방 문제

01 가방 문제
제목.
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; }


 

좋은 웹페이지 즐겨찾기