2017年院赛E题 守望者的逃离

来源:互联网 发布:知乎 风扇灯什么牌子好 编辑:程序博客网 时间:2024/06/06 03:34

目录:

2017年院赛A题 Neptune'Pudding

2017年院赛B题 N个数求和

2017年院赛C题 treat

2017年院赛D题 简单加密

2017年院赛E题 守望者的逃离

2017年院赛F题 数独游戏

2017年院赛G题 忠诚

2017年院赛H题 最大异或和


题目:

Description:
恶魔猎手尤迪安野心勃勃,她背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变。守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上。为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会沉下去。到那时,岛上的所有人都会遇难。守望者的跑步速度为17m/s,以这样的速度是无法逃离荒岛的。庆幸的是守望者拥有闪烁法术,可在1s内移动60m,不过每次使用闪烁法术都会消耗魔法值10点。守望者的魔法值恢复的速度为4点/s,只有处在原地休息状态时才能恢复。 
现在一直守望者的魔法初值M,他所在的初始位置与岛的出口之间的距离S,岛沉没的时间T。你的任务是写一个程序帮助守望者计算如何在最短的时间内逃离荒岛,若不能逃出,则输出守望者在剩下的时间内能走的最远距离。注意:守望者跑步、闪烁或休息活动均以秒(s)为单位,且每次活动的持续时间为正数秒。距离单位为米(m)。
Input:
第一行一个整数t,代表有t组数据,接下来t行,每一行包括空格隔开的三个非负整数M, S, T。
Output:
对于每一组数据输出两行,第1行为字符串“Yes”或“No”(区分大小写),即守望者是否能逃离荒岛。第2行包含一个整数。第一行为“Yes”(区分大小写)时表示守望者逃离荒岛的最短时间;第一行为“No”(区分大小写)时表示守望者能走的最远距离。
SampleInput:
1
39 200 4
SampleOutput:
No
197


标程:

#include <iostream>#include <cstdio>using namespace std;int main(){ios_base::sync_with_stdio(0);int m, s, t, times;cin>>times;while(times--){cin >> m >> s >> t;int m_n=m, s_n=0, t_n=0;while (t_n < t&&s_n < s){if (m_n >= 10)m_n -= 10, s_n += 60,++t_n;else if (m_n>=6){if (s - s_n <= 17||t-t_n==1)++t_n, s_n += 17;elsem_n -= 6, s_n += 60, t_n += 2;}else if (m_n >= 2){if (t - t_n <= 2)s_n += 17, ++t_n;else if (s - s_n <= 34)++t_n, s_n += 17;elsem_n -= 2, s_n += 60, t_n += 3;}else{if (t - t_n <= 6)s_n += 17, ++t_n;else if (s - s_n <= 102)++t_n, s_n += 17;elset_n += 7, s_n += 120;}}cout << ((s_n >= s) ? ("Yes") : ("No")) << endl << ((s_n >= s) ? t_n : s_n)<<endl;}return 0;}


因为题目没写m,s,t的范围,所以我考虑的是三个数都是int范围内的任意数,也就是说我提交的是一个O(1)的算法,原理是在O(1)的时间内将问题转化成2个子问题,而这2个中的参数都小于某个很小的常数。这个方法,和POJ 1915 Knight Moves里面的方法如出一辙。

我的代码:

#include<iostream>using namespace std;int time2(int m,int s){if(s<=0)return 0;if(m>=10)return time2(m-10,s-60)+1;int k=time2(m+4,s)+1;if(k>(s+16)/17)k=(s+16)/17;return k;}int time(int m,int s){int k=m/10;m-=k*10;if(s<=k*60)return (s+59)/60;if(k)return time(m,s-k*60)+k;k=s/120-1;if(k>0)return time(m,s-k*120)+k*7;return time2(m,s);}int len(int m,int t){if(t==0)return 0;int k=m/10;m-=k*10;if(t<k)return t*60;if(k)return len(m,t-k)+k*60;k=t/7-1;if(k>0)return len(m,t-k*7)+k*120;k=len(m+4,t-1);if(k<t*17)k=t*17;return k;}int main(){int T,m,s,t,ans;cin>>T;while(T--){cin>>m>>s>>t;ans=time(m,s);if(ans<=t)cout<<"Yes\n"<<ans<<endl;else cout<<"No\n"<<len(m,t)<<endl;}return 0;}
其实函数time和time2是不用分离的,但是为了更好的防止死循环,还是分开写了,直接把time2的代码复制到time里面调用time2地方应该也是正确的。


0 0
原创粉丝点击