题目描述
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;
}
本题结。