题目:
链接:点击打开链接
题意:
xx喜欢收集鞋子,n,m,k分别表示鞋子的总数,xx的钱和鞋子的品牌数目。然后给出每个鞋子的信息有:a,是那种品牌,b,鞋子的标价,c,收藏鞋子得到的价值。对于一个收藏家来说,每种品牌的鞋子只收集一种,求出xx能够得到的最大的收藏价值。
算法:
分组背包问题。
思路:
m总的钱数是背包容量,k品牌数是组数。用数组结构体保存每种鞋子的信息,d[i][j].w表示第i种品牌的鞋子中的第j个鞋子的标价,d[i][j].v表示第i种品牌的鞋子中的第j个鞋子价值。状态转移方程dp[i][j]表示前i组品牌中用掉j钱得到的最大的价值。状态转移可以是前一组少取一个,即dp[i-1][p-d[i][j].w]+d[i][j].v,也可以是当前组少取一种,即dp[i][p-d[i][j].w]+d[i][j].v。初始化第一组置为0,其他组置为负无穷,因为只有上一组达到要求才能进行下一组,每组必须取一个。
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; struct node{ int v; int w; }d[20][110]; int num[20]; int dp[20][10010]; int main() { //freopen("input.txt","r",stdin); int n,m,k; int a,b,c; while(scanf("%d%d%d",&n,&m,&k) != EOF) { memset(num,0,sizeof(num)); memset(dp,-1,sizeof(dp)); for(int i=1; i<=n; i++) { scanf("%d%d%d",&a,&b,&c); d[a][num[a]].w = b; d[a][num[a]].v = c; num[a]++;//num[a]表示第a组的鞋的个数 } memset(dp[0],0,sizeof(dp[0])); for(int i=1; i<=k; i++) { for(int j=0; j<num[i]; j++) { for(int p=m; p>=d[i][j].w; p--) { if(dp[i-1][p-d[i][j].w] != -1) dp[i][p] = max(dp[i][p],dp[i-1][p-d[i][j].w]+d[i][j].v); if(dp[i][p-d[i][j].w] != -1) dp[i][p] = max(dp[i][p],dp[i][p-d[i][j].w]+d[i][j].v); } } } if(dp[k][m] == -1) printf("Impossible\n"); else printf("%d\n",dp[k][m]); } return 0; }
hdu 3033 I love sneakers!,布布扣,bubuko.com
原文地址:http://blog.csdn.net/u013147615/article/details/27094643