HDOJ 3535 AreYouBusy (背包 每组至少一个)

题目链接:(—_—) zZ


题目大意:有n种工作的集合, 每种集合有一种类型, 0为最少在这个集合中选一个工作, 1为最多在这个集合中选一个工作, 2为随便选, 做每个工作要花一定的时间和得到一定的幸福度, 求在t时间内获得的最大幸福度


思路:类型为0时是分组背包的变形 , 为1时就是分组背包, 为2是为0-1背包,分别根据背包类型求出就可

Ps:无限wa


code:

#include <stdio.h>
#include <string.h>
struct node
{
    int t, h;
}pack[5][100002];
int c = 0, n = 0, t = 0,dp[102][102], num[5][102], index1[5], ind[102];
void zeropack( int in, int start)//至少选一个
{
    int i = 0, j = 0, k  = 0, tpval = 0;
    for(i = 0; i<num[0][in]; i++)
    {
        for(j = t; j>=pack[0][start+i].t; j--)
        {
            if(dp[c][j-pack[0][start+i].t] != -1)
                dp[c][j] = dp[c][j]>dp[c][j-pack[0][start+i].t]+pack[0][start+i].h? dp[c][j]:dp[c][j-pack[0][start+i].t]+pack[0][start+i].h;
            if(dp[c-1][j-pack[0][start+i].t] != -1)
                dp[c][j] = dp[c][j]>dp[c-1][j-pack[0][start+i].t]+pack[0][start+i].h? dp[c][j]:dp[c-1][j-pack[0][start+i].t]+pack[0][start+i].h;
        }
    }
}

void onepack(int in, int start)//最多选一个 分组背包问题
{
    int i = 0, j = 0, k = 0, tpval = 0;
    for(i = 0; i<=t; i++)
        dp[c][i] = dp[c-1][i];
    for(i = t; i>=0; i--)
    {
        for(j = 0; j<num[1][in]; j++)
            if(pack[1][start+j].t<=i && dp[c-1][i-pack[1][start+j].t] != -1)
                dp[c][i] = dp[c][i]>dp[c-1][i-pack[1][start+j].t]+pack[1][start+j].h? dp[c][i]:dp[c-1][i-pack[1][start+j].t]+pack[1][start+j].h;
    }
}

void twopack(int in, int start)//0-1背包
{
    int i = 0, j =0, k = 0, tpval = 0;
    for(i = 0; i<=t; i++)
        dp[c][i] = dp[c-1][i];
    for(i = 0; i<num[2][in]; i++)
    {
        for(j = t; j>=pack[2][start+i].t; j--)
        {
            if(dp[c][j-pack[2][start+i].t] != -1 )
                dp[c][j] = dp[c][j]>dp[c][j-pack[2][start+i].t]+pack[2][start+i].h? dp[c][j]:dp[c][j-pack[2][start+i].t]+pack[2][start+i].h;
        }
    }
    c++;
}

int main()
{
    int i = 0, j = 0, m = 0, s = 0, start = 0, ans = -1;
    while(scanf("%d %d", &n, &t) != EOF)
    {
        c = 1;
        memset(index1, 0, sizeof(index1));
        memset(ind, 0, sizeof(ind));
        memset(dp, -1, sizeof(dp));
        for(i = 0; i<=t; i++)
            dp[0][i] = 0;
        for(i = 0; i<n; i++)
        {
            scanf("%d %d", &m, &s);
            num[s][index1[s]++] = m;//index1[s]表示有多少类为s的组
            for(j =0; j<m; j++, ind[s]++)
            {
                scanf("%d", &pack[s][ind[s]].t);
                scanf("%d", &pack[s][ind[s]].h);
            }
        }
            start = 0;
         for(j = 0; j<index1[0]; j++)//一共有多少组类属于0的
          {
          zeropack(j, start);
              start += num[0][j];
              c++;
          }
          start = 0;
          for(j = 0; j<index1[1]; j++)
          {
              onepack(j, start);
              start += num[1][j];
              c++;
          }
          start = 0;
          for(j = 0; j<index1[2]; j++)
          {
              twopack(j, start);
              start += num[2][j];
          }
         printf("%d\n", dp[c-1][t]);
  }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值