uestc oj 1500 AreYouBusy (2)

AreYouBusy
   好像是一个背包问题
   一共有三类物品
   dp[i][j]  表示的是第i组,时间为j的最大快乐值  每得到一组工作就进行一次DP  
   第一类  至少选一项 状态方程  dp[i][j]=max(dp[i][j],max(dp[i][j-w[x]]+p[x],dp[i-1][j-time[x]]+happ[x]));
   dp[i-1][j-time[x]]+happ[x]其实表示第一次在本组中选物品  其实在一次选择之后这个值移动后就没有用了 因为他一定会小于等于
   dp[i][j-time[x]]+happ[x]  在将本组中所有物品遍历一遍后至少会选取一件    
   在这一类操作时,因为至少选一项,要避免都不选的情况(就是说这一组的数据很奇怪,选了之后在同等时间下快乐值反而减少了)
   所以在计算之前需要给dp[i][j]  赋初值为极小值  这样的话就不会出现上述情况了。
   第二类  至多选一项  状态方程
   当然在之前要将  dp[i][j] = dp[i-1][j]
   dp[i][j]=max(dp[i][j],dp[i-1][j-time[x]]+happ[x]);
   第三类  随便选
   首先还是要将    dp[i][j] = dp[i-1][j]
   然后
   dp[i][j]=max(dp[i][j],dp[i][j-time[k]]+happ[k]);
   




#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 0xfffffff
using namespace std;


int dp[105][105];
int time[105];
int happ[105];
int n,t,i,j,c,g,k;


int main()
{
    //freopen("1.txt","r",stdin);
    while(scanf("%d%d",&n,&t)==2)
    {
          //for(i=0;i<=n;i++)
          //memset(dp,0,sizeof(dp[i]));
          memset(dp,0,sizeof(dp));
          for(i=1;i<=n;i++)
          {
             scanf("%d%d",&c,&g);
             for(j=0;j<c;j++)
                scanf("%d%d",&time[j],&happ[j]);


             switch(g)
             {
                 case 0:
                     //memset(dp,-inf,sizeof(dp[i]));
                     for(j=0;j<=t;j++)
                       dp[i][j]=-inf;
                     for(k=0;k<c;k++)
                       for(j=t;j>=time[k];j--)
                       dp[i][j]=max(dp[i][j],max(dp[i][j-time[k]]+happ[k],dp[i-1][j-time[k]]+happ[k]));
                 break;


                 case 1:
                     for(j=0;j<=t;j++)
                        dp[i][j]=dp[i-1][j];
                     for(k=0;k<c;k++) 
                       for(j=t;j>=time[k];j--)
                       dp[i][j]=max(dp[i][j],dp[i-1][j-time[k]]+happ[k]);
                 break;


                 case 2:
                    for(j=0;j<=t;j++)
                        dp[i][j]=dp[i-1][j];
                    for(k=0;k<c;k++) 
                       for(j=t;j>=time[k];j--)
                       dp[i][j]=max(dp[i][j],dp[i][j-time[k]]+happ[k]);
                 break;
             }
          }
          dp[n][t]=max(dp[n][t],-1);
          printf("%d\n",dp[n][t]);


    }
    return 0;
}
 				    


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值