题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2159
解题报告:这题实际上是一个二维的背包问题,也可以由01背包扩展而来,01背包用一维数组,可想而知二维背包应该二维数组,然后每一维表示它的一种不同的需要付出的代价,普通的二维背包的递推公式是dp[j][k] = max(dp[j][k],w[j-v[i][k-n[i]] + w[i]);,要注意的是这是一般的二维背包的递推公式,但是在这题中有一点小小的变化,就是
怪的个数有无限个,也就是说每件物品都可以取无限次,所以还要再加上一层循环,这个应该简单。具体见代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 struct node 7 { 8 int a,b,exp; 9 node() 10 { 11 b = 1; 12 } 13 }guai[105]; 14 int E[105][105],flag[105]; 15 16 int main() 17 { 18 int n,m,k,s; 19 while(scanf("%d%d%d%d",&n,&m,&k,&s)!=EOF) 20 { 21 for(int i = 0;i < k;++i) 22 scanf("%d%d",&guai[i].exp,&guai[i].a); 23 memset(E,0,sizeof(E)); 24 memset(flag,0,sizeof(flag)); 25 int ans = 102; 26 for(int i = 0;i < k;++i) 27 for(int jk = 0;jk <= min(m / guai[i].a,s / guai[i].b);++jk) 28 for(int j = m;j >= jk * guai[i].a;--j) 29 for(int k = s;k >= jk * guai[i].b;--k) 30 if(E[j][k] < E[j-jk * guai[i].a][k-jk * guai[i].b] + jk * guai[i].exp) 31 { 32 flag[i] = 1; 33 E[j][k] = E[j-jk * guai[i].a][k-jk * guai[i].b] + jk * guai[i].exp; 34 if(E[j][k] >= n) 35 ans = min(ans,j); 36 } 37 if(E[m][s] >= n) 38 printf("%d ",m - ans); 39 else printf("-1 "); 40 } 41 return 0; 42 }