[练习]背包DP 竞赛得分

题目描述
ZZH 在经历了无数次学科竞赛的失败以后,得到了一个真理:做一题就要对一题!但是要完全正确地做对一题是要花很多时间(包括调试时间),而竞赛的时间有限。所以开始做题之前最好先认真审题,估计一下每一题如果要完全正确地做出来所需要的时间,然后选择一些有把握的题目先做。 当然,如果做完了预先选择的题目之后还有时间,但是这些时间又不足以完全解决一道题目,应该把其他的题目用贪心之类的算法随便做做,争取“骗”一点分数。根据每一题解题时间的估计值,确定一种做题方案(即哪些题目认真做,哪些题目“骗”分,哪些不做),使能在限定的时间内获得最高的得分。

输入格式
第一行有两个正整数 N 和 T,表示题目的总数以及竞赛的时限(单位秒)。以下的 N 行,每行 4 个正整数 W1i 、T1i 、W2i 、T2i ,分别表示第 i 题:完全正确做出来的得分、完全正确做出来所花费的时间(单位秒)、“骗”来的分数、“骗”分所花费的时间(单位秒)。

其中,3≤N≤30,2≤T≤1080000,1≤W1i ,W2i≤30000; 1≤T1i,T2i≤T。

输出格式
输出所能得到的最高分值。

样例数据1
输入

4 10800
18 3600 3 1800
22 4000 12 3000
28 6000 0 3000
32 8000 24 6000

输出

50

样例数据2
输入

3 7200
50 5400 10 900
50 7200 10 900
50 5400 10 900

输出

70

分析:第二次做了,还是有点懵逼。枚举每一道题,再枚举每一个时间点做或者骗能得到的最优值,用来更新整体的最优值。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;

int getint()
{
    int sum=0,f=1;
    char ch;
    for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
    if(ch=='-')
    {
        f=-1;
        ch=getchar();
    }
    for(;isdigit(ch);ch=getchar())
        sum=(sum<<3)+(sum<<1)+ch-48;
    return sum*f;
}

const int N=35;
const int W=1080005;
int w1[N],v1[N],w2[N],v2[N],n,t;
int dp[W],dp1[W],dp2[W];

int main()
{
    freopen("jsdf.in","r",stdin);
    freopen("jsdf.out","w",stdout);

    n=getint();t=getint();
    for(int i=1;i<=n;++i)
        v1[i]=getint(),w1[i]=getint(),v2[i]=getint(),w2[i]=getint();

    for(int i=1;i<=n;++i)
    {
        for(int j=w1[i];j<=t;++j)
            dp1[j]=max(dp1[j],dp[j-w1[i]]+v1[i]);//当年一直把dp看成dp1,懵逼
        for(int j=w2[i];j<=t;++j)
            dp2[j]=max(dp2[j],dp[j-w2[i]]+v2[i]);
        for(int j=min(w1[i],w2[i]);j<=t;++j)
            dp[j]=max(dp1[j],dp2[j]);
    }

    int ans=0;
    for(int j=1;j<=t;++j)
        ans=max(ans,dp[j]);
    cout<<ans<<'\n';
    return 0;
}

本题结。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值