题目大意:
我们控制一个人,他的初始魔力值为M。每一秒他有三个动作,分别是:不耗魔继续往前跑17米,或者耗10点魔力使用闪烁往前60米,或者停止不动魔加4点。
现在给定时间T,问是否能走到S
已知M,S,T。其中M代表魔力值,S代表距离,T代表时间。
解题思路:
首先,我们可以容易看出,若初始有魔的话,最好让魔只剩m%=10,因为耗完所有闪烁次数是最合理的。
然后,我们看到若状态为
state=[time][mona],其中time代表还剩多少时间,mona为还剩多少魔力值,表示还剩time,mona时最远能走多少,那么我们可以得到
if mona<10
memo[time][mona]= max(memo[time-1][mona+4],memo[time-1][mona]+17)
else
memo[time][mona]= max(max(memo[time-1][mona+4],memo[time-1][mona]+17),memo[time-1][mona-10]+60)
其中边界条件为:
if mona>=10
memo[1][mona]=60
else
memo[1][mona]=17
但是,我们发现memo空间为1e8,超过了空间复杂度1e7,那么我们要进行空间压缩,我们发现每一个时刻的状态只和下一个时刻的状态有关,所以[time]这一栏可以变为[2],即
state=[2][mona]
#include <bits/stdc++.h>
using namespace std;
const int MAXM = 1020;
int memo[2][MAXM];
int main(){
int m,s,t;
cin>>m>>s>>t;
int times=m/10;
m=m%10;
if(times<=t){
if(times*60 >=s){
cout<<"Yes"<<endl;
double ans=ceil((double)s/60);
cout<<(int)ans<<endl;
exit(0);
}
else{
s-=times*60;
t-=times;
}
}else{
if(t*60>=s){
cout<<"Yes"<<endl;
double ans=ceil((double)s/60);
cout<<(int)ans<<endl;
exit(0);
}
else{
cout<<"No"<<endl;
cout<<t*60<<endl;
exit(0);
}
}
int cur=1;
memset(memo,0,sizeof(memo));
for(int time=1;time<=t;time++){
cur=!cur;
for(int mona=0;mona<=m+20;mona++){
if(time==1){
if(mona>=10)
memo[cur][mona]=60;
else memo[cur][mona]=17;
continue;
}
if(mona<10){
memo[cur][mona]=max(memo[!cur][mona]+17,memo[!cur][mona+4]);
}else{
memo[cur][mona]=max(memo[!cur][mona]+17,memo[!cur][mona-10]+60);
memo[cur][mona]=max(memo[cur][mona],memo[!cur][mona+4]);
}
}
if(memo[cur][m]>=s){
cout<<"Yes"<<endl;
cout<<time+times<<endl;
exit(0);
}
}
cout<<"No"<<endl;
cout<<memo[cur][m]+times*60<<endl;
return 0;
}