算法之路之征服上海交大的oj-西西弗斯式的命运
- 西西弗斯式的命运
Description
古希腊有个关于西西弗斯的神话:
西西弗斯被众神判决推运一块石头至山顶。由于巨石本身的重量,它被推到山顶却又总要滚下山脚。于是西西弗斯又得把石块推上山去。如此反复,永无止境,没有尽头。众神认为,让西西弗斯服这永恒的劳役是最严酷的惩罚。
二哥被押入地狱。他被众神判决扛着一块巨砖在山路上走,再原路返回,如此反复,没有尽头。
众神规定二哥独自走山路的时间不得超过M秒( 1≤M≤10,000,000
)。整条山路被划分成T个长度相同的小段( 1≤T≤100,000
),并且,众神用Si表示第i个小段的路况。Si为u,f,d这3个字母之一,它们分别表示第i个小段是上坡、平地、下坡。
二哥要花U秒( 1≤U≤100
)才能走完一段上坡路,走完一段平地的耗时是F秒( 1≤F≤100 ),走完一段下坡路要花D秒( 1≤D≤100
)。注意,沿山路原路返回的时候,原本是上坡的路段变成了下坡路,原本是下坡的路段变成了上坡路。
二哥对生活充满激情,但他遭受着难以用言语尽述的非人折磨:痛苦扭曲的脸,被巨砖死死压住的抖动的肩膀,沾满泥土的双脚,呕心沥血,不停的工作。这是典型的西西弗斯式的命运。贝多芬,歌德,叔本华,你才,还有高斯,爱因斯坦的命运,都是典型的西西弗斯式的命运,无一例外。
众神想让二哥能在按时返回的前提下,走最远的路。所以众神向知道他最多能在这条山路上走多远。
Input Format
第1行:5个空格隔开的整数:M,T,U,F,D。
第2..T+1行:第i+1行有一个字母Si,描述第i段山路的路况。
Output Format
一行,有一个整数为二哥在按时回到起点前提下,最多能跑到多远。
Sample Input
13 5 3 2 1
u
f
u
d
f
Sample Output
3
样例解释
众神规定二哥的最大耗时为13秒,他跑步的山路一共被划分成5段。二哥走完一段上坡的耗时为3秒,平地为2秒,下坡为1秒。
二哥走完山路的前3段,然后返回,总耗时为3+2+3+1+2+1=12秒,如果他跑得更远,就无法按时回到起点。
刚开始看到这道题的时候我是想用一个很暴力的方法的解决这个问题,但是超时了只能得到90分,最后想了想,其实这题没必要这么大题小作。
所以再这里也贴一下我超时的代码吧!
//请大家引以为戒,不要把代码复杂化了
超时代码:
#include<iostream>
using namespace std;
char a[100000];
int countSecond,T,U,F,D;
int change(char ch){//回
switch(ch){
case 'u':return D;
case 'f':return F;
case 'd':return U;
}
return 0;
}
int change2(char ch){//去
switch(ch){
case 'u':return U;
case 'f':return F;
case 'd':return D;
}
return 0;
}
int killThis(int t){
int count = 0;
for(int i=0;i<t;i++){
count+=change2(a[i]);
}
for(int i=t-1;i>=0;i--){
count+=change(a[i]);
}
return count;
}
int main(){
cin>>countSecond>>T>>U>>F>>D;
for(int i=0;i<T;i++){
cin>>a[i];
}
int max;
for(int i=0;;i++){
if(killThis(i)<=countSecond && killThis(i+1)>countSecond) {
max = i;
break;
}
}
cout<<max;
return 0;
}
这里是改良后,能得满分的代码:
#include<iostream>
using namespace std;
char a[100000];
int countSecond,T,U,F,D;
int main(){
cin>>countSecond>>T>>U>>F>>D;
int max1=0;
int max2=0;
for(int i=0;i<T;i++){
cin>>a[i];
if(a[i] == 'u'|| a[i] == 'd'){//判断时上下坡
max1+=(U+D);
}
if(a[i] == 'f'){//判断是否平地
max1+=2*F;
}
if(max1<=countSecond) {
max2 = i+1;
}
}
cout<<max2;
return 0;
}