有趣的背包。

题目大意

    你现在有一个背包,现在每个物品都有体积,价值,颜色三种属性,求不少于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专用小尾巴。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值