bool f[100010]; int use[100010]; int main() { int cash,n,i,j,c[15],v[15]; freopen("1276.txt","r",stdin); while(scanf("%d%d",&cash,&n)!=EOF) { for(i=1;i<=n;i++){ scanf("%d%d",c+i,v+i); if(v[i]>cash) c[i]=0; } if(cash==0||n==0) { puts("0"); continue; } memset(f,0,sizeof(f)); f[0]=1; for(i=1;i<=n;i++){ if(c[i]==0) continue; memset(use,0,sizeof(use)); for(j=v[i];j<=cash;j++){ if(!f[j]&&f[j-v[i]]&&use[j-v[i]]<c[i]){ f[j]=1; use[j]=use[j-v[i]]+1; } } } for(i=cash;;i--) if(f[i]){ printf("%d\n",i); break; } } }
PKU1014
[问题描述]
给出6堆大理石每堆的石子数目,每堆分别对应各自重量。6堆重量分别为1,2,3,4,5,6
问是否能把这些大理石分为重量相同的两堆
[问题上限]
大理石最多总共20000块
明显的多重背包问题,首先确定所有石子的总重量,如果为奇数当然是不可能平分的,否则设背包容量为sum/2,是否刚好能取一些石子使得重量刚好装满背包。
bool f[120010]; int use[120010]; int main() { int i,j,sum,c[10],TT=0; while(1){ sum=0; for(i=1;i<=6;i++){ scanf("%d",c+i); sum+= i*c[i]; } if(sum==0) break; printf("Collection#%d:\n",++TT); if(sum&1) { puts("Can'tbe divided.\n"); continue; } sum/=2; memset(f,0,sizeof(f)); f[0]=1; for(i=1;i<=6;i++){ if(c[i]==0) continue; memset(use,0,sizeof(use)); for(j=i;j<=sum;j++){ if(!f[j]&&f[j-i]&&use[j-i]<c[i]){ f[j]=1; use[j]= use[j-i]+1; } } } if(f[sum]) puts("Canbe divided.\n"); else puts("Can'tbe divided.\n"); } }
PKU1276
有N种面值的钞票,其中面值为Di的钞票有ni种,
如N=3, n1=10, D1=100, n2=4, D2=50, n3=5, D3=10; 问用这些钞票能组合出来的
面值中不超过某给定数cash的最大值是多少?
可以使用上一题的模板: