HDU 2159 FATE (二维背包)

题目链接: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\n",m - ans);
39         else printf("-1\n");
40     }
41     return 0;
42 }
View Code

 

posted @ 2014-03-17 20:59  xiaxiaosheng  阅读(218)  评论(0编辑  收藏  举报