众所周知,敢玩手机游戏的人不是氯金大佬(能充钱)就是绝世肝帝(大量时间在线)。ZEY最近迷上了一款手机游戏,当然,ZEY非常穷,只能投入大量时间来肝任务,尽管ZEY浑身是肝,但是面对阴险的游戏策划,他终于肝!不!动!了!
现在这款游戏又在周末搞活动了,要达成活动成就需要不低于 n n n 点活跃值,在活动期间有 k k k 种任务可以完成,每种任务都能够不断重复完成。不过ZEY看到这个活动已经恶心到想吐了,如果他的恶心程度超过 m m m 点,他就会晕倒!(那当然就不能继续完成活动任务了)另外,ZEY发现明天就是星期一,但是自己—点作业都没写,所以他最多还能玩 t t t 个时间单位的游戏。
已知完成第 i i i 个任务,可以获得 x [ i ] x_{[i]} x[i] 点活跃值,但是ZEY也会增加 y [ i ] y_{[i]} y[i]点恶心度,同时会消耗 1 1 1 点单位时间。现在,ZEY想知道自己能不能达成活动成就,如果能达成,他还想知道自己最多能有多不恶心(用 m m m 减去累计的恶心度);如果不能达成,他也想知道最多可以获得多少活跃值。
输入文件名为task.in。输入为多行
第一行输入4个整数,分别是 k , n , m , t k,n,m,t k,n,m,t ,数字间用空格隔开
接下来k行,每—行输入两个整数,分别是 x [ i ] x_{[i]} x[i] 和 y [ i ] y_{[i]} y[i]
输出文件名为task.out。输出—行,分两种情况:
1 5 5 5 5
1 1
输出样例1:
Y 0
输入样例2:
2 12 8 3
3 1
4 3
输入样例2:
N 11
对于样例1,完成 5 5 5 次人物刚好达成成就,不恶心程度为 0 0 0 。
对于样例2,容易证明无法达成,当完成1次人物1或2次任务2时,活跃值最大为 11 11 11 。
1 ≤ , n , m , t ≤ 150 1\le ,n,m,t\le 150 1≤,n,m,t≤150 , 1 ≤ x i , y i ≤ 20 1\le x_i,y_i\le 20 1≤xi,yi≤20 。
题目考点:动态规划,动规,dp。背包。
背包特点:二维背包。
方程: d p j , p = m a x ( d p j , p , d p j − 1 , p − k k k i , 1 + k k k i , 0 ) dp_{j,p}=max(dp_{j,p},dp_{j-1,p-kkk_{i,1}}+kkk_{i,0}) dpj,p=max(dpj,p,dpj−1,p−kkki,1+kkki,0) 。其中 k k k i , 0 kkk_{i,0} kkki,0 为活跃值(即 x i x_i xi ), k k k i , 1 kkk_{i,1} kkki,1 为恶心度(即 y i y_i yi ), j j j 为时间, p p p 为恶心度。
翻译方程: 对于第 i i i 个活动:
选择方案是选最大值,所以 d p j , p = m a x ( d p j , p , d p j − 1 , p − k k k i , 1 + k k k i , 0 ) dp_{j,p}=max(dp_{j,p},dp_{j-1,p-kkk_{i,1}}+kkk_{i,0}) dpj,p=max(dpj,p,dpj−1,p−kkki,1+kkki,0) 。
所以代码:
for(int i=1;i<=k;++i)
for(int j=1;j<=t;++j)
for(int p=kkk[i][1];p<=m;++p)
dp[j][p]=max(dp[j][p],dp[j-1][p-kkk[i][1]]+kkk[i][0]);
但是题目要求求最不恶心程度,所以设置一个bool类型的变量来设置,如下:
bool fff=false;
/*循环代码跳过,方程跳过。*/
if(dp[j][p]>=n)fff=true,ans=max(ans,m-p);
这里求的是最不恶心程度的最大值,也可以求最恶心程度的最小值。即
ans=0x7f7f7f7f7f;
/*省略一些代码*/ans=min(ans,p);
输出: m − a n s m-ans m−ans
然后就贴代码:
#include
#include
using namespace std;
class QIO{
public:
inline int read(){
x=0,f=1,ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-f;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*f;
}
inline void write(int a){
if(a<0)a=-a,putchar('-');
output((unsigned int)a);
}
private:
void output(unsigned int a){
if(a>9)output(a/10);
putchar((a%10)^48);
}
int x;
short f;
char ch;
};
QIO qrw;//快速输入输出
int kkk[200][2],dp[1001][1001];
signed main(){
freopen("task.in","r",stdin);
freopen("task.out","w",stdout);
int k,n,m,t,ans=0;
k=qrw.read();
n=qrw.read();
m=qrw.read();
t=qrw.read();
bool fff=false;
for(int i=1;i<=k;++i){
kkk[i][0]=qrw.read();
kkk[i][1]=qrw.read();
}
for(int i=1;i<=k;++i)
for(int j=1;j<=t;++j)
for(int p=kkk[i][1];p<=m;++p){
dp[j][p]=max(dp[j][p],dp[j-1][p-kkk[i][1]]+kkk[i][0]);
if(dp[j][p]>=n)fff=true,ans=max(ans,m-p);
}
if(fff){
putchar('Y');
putchar(' ');
qrw.write(ans);
}else{
putchar('N');
putchar(' ');
qrw.write(dp[t][m]);
}
return 0;
}