HDU3033I love sneakers!(分组背包)
http://acm.hdu.edu.cn/showproblem.php?pid=3033
本题的意思就是说现在有n种牌子的鞋子,每种品牌有一些不同的鞋,每双鞋子都有一个特定的权值,现在要求每种品牌的鞋子都至少收集一双,有一定量的钱,问获得的最大的权值是多少。
这个题与普通的分组背包不同就在于每一组都至少选一个,(正好这个难道我了= =)
网上找了解题报告,解题方法很巧妙,就是先将每一个DP值初始化为一个值,比如-1,表示所有的状态都不合法
那么转移方程就是
if(DP[i][k-cost[i][j]] != -1) DP[i][k] = max(DP[i][k], DP[i][k-cost[i][j]]+val[i][j]); if(DP[i-1][k-cost[i][j]] != -1) DP[i][k] = max(DP[i][k], DP[i-1][k-cost[i][j]]+val[i][j]);
这样一来,如果要得到一个DP值,就必须从一个合法的状态得到,首先,如果DP[i][k-cost[i][j]]!=-1,那么说明这一层已经存放了物品,否则就是没有放那么就必须从上一层的状态转移得到。
得解。
见代码:
1 #include <map> 2 #include <set> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <vector> 8 #include <cstdio> 9 #include <cctype> 10 #include <cstring> 11 #include <cstdlib> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 #define INF 0x3f3f3f3f 16 #define MAX(a,b) (a > b ? a : b) 17 #define MIN(a,b) (a < b ? a : b) 18 #define lson k<<1, L, mid 19 #define rson k<<1|1, mid+1, R 20 #define mem0(a) memset(a,0,sizeof(a)) 21 22 typedef long long LL; 23 const double eps = 1e-12; 24 const int MAXN = 1005; 25 const int MAXM = 5005; 26 27 int num[11],cost[11][110], val[11][110]; 28 int DP[11][11000], sum; 29 int N, M, K; 30 31 void init() 32 { 33 mem0(DP); mem0(cost);mem0(val);mem0(num); 34 num[0] = 1; 35 } 36 37 void ReadData() 38 { 39 int a, b, c; 40 for(int i=0;i<N;i++) 41 { 42 scanf("%d%d%d", &a, &b, &c); 43 cost[a][num[a]] = b; 44 val[a][num[a]] = c; 45 num[a]++; 46 } 47 } 48 49 int main() 50 { 51 while(~scanf("%d %d %d", &N, &M, &K)) 52 { 53 init(); 54 ReadData(); 55 for(int i=0;i<=K;i++) 56 { 57 for(int j=0;j<=M;j++) 58 { 59 DP[i][j] = i==0?0:-1; 60 } 61 } 62 for(int i=1;i<=K;i++) 63 { 64 for(int j=0;j<num[i];j++) 65 { 66 for(int k=M;k>=cost[i][j];k--) 67 { 68 if(DP[i][k-cost[i][j]] != -1) 69 DP[i][k] = max(DP[i][k], DP[i][k-cost[i][j]]+val[i][j]); 70 if(DP[i-1][k-cost[i][j]] != -1) 71 DP[i][k] = max(DP[i][k], DP[i-1][k-cost[i][j]]+val[i][j]); 72 } 73 } 74 } 75 if(DP[K][M]<0)printf("Impossible\n"); 76 else printf("%d\n",DP[K][M]); 77 } 78 return 0; 79 }