hdu-3033 又见0-1背包

来源:互联网 发布:草图大师网络 编辑:程序博客网 时间:2024/06/02 20:04

这个是稍微复杂的0-1背包,或者可以说是二维背包的变形。总之,就是一个特殊背包,特殊在哪呢?稍后分析

题意:

某人要买鞋,有k个品牌,每个品牌有j个款,每款都有标价和价值,要求已经M元内,每个品牌至少买一双鞋的最大价值和。

分析:

难点1 每个品牌至少一双,很令人纠结呀。

其实的其实,可以这样想,k个品牌,可以直接理解为重量为k,只要k全部填满,即为k个品牌至少一个。

理解了这个就不难知道,DP[i][j]代表,第i个品牌,资金数为j的最大价值和。

难点2 状态转移方程 这个比较费神,怎么个转移法呀,子状态是什么呢。

可以这样想,当前在放置第i个品牌的第j个物品,那么有四种状态

a,,第i个品牌未放置过,第j个物品不放置DP[i-1][w];//值不变

b,第i个品牌未放置过,第j个物品要放置DP[i-1][w-N[i][j].b];

c,第i个品牌已放置过,第j个物品也放置DP[i][w-N[i][j].b];

d,第i个品牌已放置过,第j个物品不放置DP[i][w]。//值不变

好吧 看似很难得题分析完  也就很好理解了、、、、不枉费苦思冥想几天呀

写题中看到一篇文章,讲解的也很不错,留个链接、、谢谢博主,(*^__^*) 嘻嘻……

代码:

#include <iostream>#include<algorithm>using namespace std;#define INF 999999#define max(a,b) (((a)>(b))?(a):(b))int sum[11];//每种品牌的商品数量struct info{int b;//标价int v;//价值}N[11][101];//每种品牌的每双鞋的信息int DP[11][10001];//i个品牌,j资金的最大价值int main(){int n,m,k,i,j,w;while(cin>>n>>m>>k)//n个鞋款,m总金额,k种品牌{memset(sum,0,sizeof(sum));int p;for(i=0;i<n;i++){cin>>p;sum[p]++;cin>>N[p][sum[p]].b>>N[p][sum[p]].v;//都是从1开始}//初始化(必须填满)for(i=0;i<=k;i++)for(j=1;j<=m;j++)DP[i][j]=-INF;for(j=1;j<=m;j++)DP[0][j]=0;for(i=1;i<=k;i++)//品牌{for(j=1;j<=sum[i];j++)//第几双鞋{for(w=m;w>=1;w--)//钱{if(w>=N[i][j].b){if(DP[i][w-N[i][j].b]!=-INF)//放过i,放jDP[i][w]=max(DP[i][w],DP[i][w-N[i][j].b]+N[i][j].v);if(DP[i-1][w-N[i][j].b]!=-INF)//未放i,放jDP[i][w]=max(DP[i][w],DP[i-1][w-N[i][j].b]+N[i][j].v);}}}}if(DP[k][m]==-INF) cout<<"Impossible"<<endl;else cout<<DP[k][m]<<endl;}return 0;}

原创粉丝点击