题目大意
你现在有一个背包,现在每个物品都有体积,价值,颜色三种属性,求不少于K种颜色
下背包的最大值。
输入
输入第一行为测试样例组数T(1<=T<=100)。
对于每组数据第一行包含三个正整数n(1<=n<=100),k(1<=k<=5),v(1<=v<=200),分别代表n个物品,想要的颜色种数,背包的容量。
接下来n行,每行三个正整数ai(1<=ai<=1000),vi(1<=vi<=v),ci(1<=ci<=n),分别代表每个物品的价值,体积,颜色。
输出
对于每组数据,输出一个整数代表背包能放不少于k种颜色的最大价值。
样例输入
3
5 1 10
3 2 1
5 8 1
7 9 1
1 2 2
2 2 3
5 2 10
3 2 1
5 8 1
7 9 1
1 2 2
2 2 3
5 3 10
3 2 1
5 8 1
7 9 1
1 2 2
2 2 3
样例输出
8
7
6
其实还是很容易想到在01背包的基础上,多加一维用来表示个数,那转移方程式也可以得到
用dp[i][j]来表示在i个颜色下体积是j的情况下,可以获得价值的最大值,用a[i][j]来表示在第i种颜色下体积是j的情况下,可以获得价值的最大值。那么dp[i][j]=max(dp[i][j],dp[i-1][j-x]+a[y][x]);
下面是代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int dp[110][300];//[该种类颜色][体积]
int dp1[110][300];[个数][体积]
int a[110];//价值
int b[110];//体积
int c[110];//颜色
bool vis[110];//标记是否有这个种类的颜色
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(vis,false,sizeof(vis));
memset(dp,-inf,sizeof(dp));
memset(dp1,-inf,sizeof(dp1));
int n,k,v;
scanf("%d%d%d",&n,&k,&v);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&a[i],&b[i],&c[i]),vis[c[i]]=true;//种类颜色
for(int i=1;i<=n;i++)
dp[i][0]=0;//初始化
for(int i=1;i<=n;i++)
{
for(int j=v;j>=b[i];j--)
{
dp[c[i]][j]=max(dp[c[i]][j],dp[c[i]][j-b[i]]+a[i]);//按颜色种类背一次
}
}
for(int i=0;i<=v;i++)
dp1[0][i]=0;//初始化
int cnt=0;
for(int i=1;i<=n;i++){
if(!vis[i])//没这种颜色
continue;
cnt++;
for(int j=cnt;j>=1;j--){
for(int k=v;k>=1;k--){
for(int l=v;l>=k;l--){
dp1[j][l]=max(dp1[j][l],dp1[j-1][l-k]+dp[i][k]);//转移方程式
}
}
}
}
int _max=0;
for(int i=k;i<=n;i++)//找出至少K种颜色最大价值
_max=max(_max,dp1[i][v]);
printf("%d\n",_max);
}
}
这道题还是很有意思,终于写出来了,呜呜呜呜呜呜。
题目链接TZOJ 5873
To live is to function --xxy专用小尾巴。