这个是稍微复杂的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,放j
DP[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,放j
DP[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;
}