【题意】
有S款运动鞋,一个n件,总钱数为m,求不超过总钱数且每款鞋子至少买一双的情况下,使价值最大。如果有一款买不到,就输出“Impossible"。
1<=N<=100 1 <= M<= 10000
【题解】
首先明显这是一个分组背包。
impossible 就直接看看每组最便宜的是否买得起。
因为每组最少选一个,所以我们可以这样dp:
f[k][j]表示当前扫到第k组,容量为j。
f[k][j]可由三个更新:
f[k][j]=f[k][j] 不选当前物品
f[k][j]=f[k-1][j-b[i]]+c[i] 选择当前物品,并且是在该组中第一次选物品
f[k][j]=f[k][j-b[i]]+c[i] 选择当前物品,并且不是在该组中第一次选
因为f[k][j]初始值为0,所以它最少都会买一样东西(由第二条更新得到)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 #include<vector> 8 using namespace std; 9 10 const int N=11000,S=110; 11 int n,m,K,a[N],b[N],c[N],mn[S],d[S][S],f[S][N]; 12 13 int maxx(int x,int y){return x>y ? x:y;} 14 int minn(int x,int y){return x<y ? x:y;} 15 16 int main() 17 { 18 freopen("a.in","r",stdin); 19 while(scanf("%d%d%d",&n,&m,&K)!=EOF) 20 { 21 memset(d,0,sizeof(d)); 22 memset(mn,63,sizeof(mn)); 23 for(int i=1;i<=n;i++) 24 { 25 scanf("%d%d%d",&a[i],&b[i],&c[i]); 26 d[a[i]][++d[a[i]][0]]=i; 27 mn[a[i]]=minn(mn[a[i]],b[i]); 28 } 29 int x=0; 30 for(int i=1;i<=K;i++) x+=mn[i]; 31 if(m<x) printf("Impossible "); 32 else 33 { 34 memset(f,0,sizeof(f)); 35 for(int k=1;k<=K;k++) 36 { 37 for(int i=1;i<=d[k][0];i++) 38 { 39 x=d[k][i]; 40 for(int j=m;j>=b[x];j--) 41 { 42 f[k][j]=maxx(f[k][j],maxx(f[k-1][j-b[x]]+c[x],f[k][j-b[x]]+c[x])); 43 } 44 } 45 } 46 printf("%d ",f[K][m]); 47 } 48 } 49 return 0; 50 }