luogu1095 守望者的逃离
题目
题目描述
恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变。守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上。为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会沉下去。到那时,岛上的所有人都会遇难。守望者的跑步速度为17m/s,以这样的速度是无法逃离荒岛的。庆幸的是守望者拥有闪烁法术,可在1s内移动60m,不过每次使用闪烁法术都会消耗魔法值10点。守望者的魔法值恢复的速度为4点/s,只有处在原地休息状态时才能恢复。
现在已知守望者的魔法初值M,他所在的初始位置与岛的出口之间的距离S,岛沉没的时间T。你的任务是写一个程序帮助守望者计算如何在最短的时间内逃离荒岛,若不能逃出,则输出守望者在剩下的时间内能走的最远距离。注意:守望者跑步、闪烁或休息活动均以秒(s)为单位,且每次活动的持续时间为整数秒。距离的单位为米(m)。
输入格式
共一行,包括空格隔开的三个非负整数M, S, T。
输出格式
共两行。
第11行为字符串“Yes”或“No”(区分大小写),即守望者是否能逃离荒岛。
第22行包含一个整数。第一行为“Yes”(区分大小写)时表示守望者逃离荒岛的最短时间;第一行为“No”(区分大小写)时表示守望者能走的最远距离。
输入输出样例
输入 #1
39 200 4
输出 #1
No 197
输入 #2
36 255 10
输出 #2
Yes 6
说明/提示
30%的数据满足:1≤T≤10,1≤S≤100
50%的数据满足:1≤T<≤1000,1≤S≤10000
100%的数据满足:1≤T≤300000,0≤M≤1000,1≤S≤108.
分析
40分错误做法
1 //m是个不确定因素,每一次的闪烁都会积累,会有剩余,所以一定程度上不满足最优子问题 2 for(int i = 1;i <= t; ++ i){ 3 dp[i] = dp[i - 1] + 17; 4 if(m >= 10) dp[i] = dp[i - 1] + 60,m -= 10; 5 else { 6 int cur = 1,m1 = m;//施魔法还需要1秒 7 //用m1临时存,如果不更新那么m是不变的 8 while(m1 < 10) ++cur,m1 += 4; 9 if(i >= cur && dp[i] < dp[i - cur] + 60) dp[i] = dp[i - cur] + 60,m = m1 - 10; 10 //更新还要消耗m值 11 } 12 if(dp[i] >= s){ 13 puts("Yes");//大小写!!! 14 put(i); 15 return;//要return 16 } 17 } 18 puts("No"); 19 put(dp[t]);
满分代码
1 /************************* 2 User:Mandy.H.Y 3 Language:c++ 4 Problem: 5 Algorithm: 6 *************************/ 7 #include<bits/stdc++.h> 8 9 using namespace std; 10 11 const int maxt = 3e5 + 5; 12 13 int m,s,t; 14 long long dp[maxt]; 15 16 char *TT,*mo,but[(1 << 15) + 2]; 17 #define getchar() ((TT == mo && (mo = ((TT = but) + fread(but,1,1 << 15,stdin)),TT == mo)) ? -1 : *TT++) 18 template<class T>inline void read(T &x){ 19 x = 0;bool flag = 0;char ch = getchar(); 20 while(!isdigit(ch)) flag |= ch == '-',ch = getchar(); 21 while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar(); 22 if(flag) x = -x; 23 } 24 25 template<class T>void putch(const T x){ 26 if(x > 9) putch(x / 10); 27 putchar(x % 10 | 48); 28 } 29 30 template<class T>void put(const T x){ 31 if(x < 0) putchar('-'),putch(-x); 32 else putch(x); 33 } 34 35 void file(){ 36 freopen("testdata(1).in","r",stdin); 37 // freopen("1095.out","w",stdout); 38 } 39 40 void readdata(){ 41 read(m);read(s);read(t); 42 } 43 44 void work(){ 45 //m是个不确定因素,每一次的闪烁都会积累,会有剩余,所以一定程度上不满足最优子问题 46 //若考虑多次闪烁的累加,多一层循环 47 // 这样我们可以预处理出闪烁/多次闪烁, 48 for(int i = 1;i <= t; ++ i){ 49 if(m >= 10) dp[i] = dp[i - 1] + 60,m -= 10; 50 else dp[i] = dp[i - 1],m +=4; 51 } 52 53 for(int i = 1;i <= t; ++ i){ 54 dp[i] = max(dp[i],dp[i - 1] + 17); 55 if(dp[i] >= s){ 56 puts("Yes"); 57 put(i); 58 return; 59 } 60 } 61 puts("No"); 62 put(dp[t]); 63 } 64 65 int main(){ 66 // file(); 67 readdata(); 68 work(); 69 return 0; 70 }
非做顽石不可,哪管他敬仰暗唾