题目:
https://www.dotcpp.com/oj/problem1108.html
这一题自己想的思路很复杂,但提交显示83% 答案错误= =
其实这一题仔细考虑的话,当M剩0/1的话,T>=7用闪烁才有意义,同理,1/2的话,也有个T的范围。。。
笔算了下,对应M为0时,用闪花的时间:
3s 1s 2s 1s 3s 1s 2s 1s ……
60m 60m 60m 60m……
M为4时,用闪花的时间:
2s 1s 2s 1s 3s 1s 2s 1s 3s 1s 2s 1s……
60 60 60 60 60 60……
如果分类讨论,真的又多又杂,而且容易出错(考虑不周全)
看了一个大神的题解豁然开朗:可以一边用闪,一边考虑这一次不用闪,两种方式的路径哪个最长?两个方案平行进行,哪一个最优,max就完事!
打个不恰当的比方,两种计算方式是两个平行宇宙,两边互不知晓对方在平行计算着,一个用闪,闪不够了就憋,另一个机械地+17,当max之后,就确定了它在此时此刻只能有一个走向,但随着时间推进,如果用闪的优势超过了+17,那么max又会成为用闪的结果,当+17更棒,结果就是+17
一个max解决所有问题,不得不说又简洁,又抓住了这题的关键
AC代码如下:
#include <stdio.h>
#define max(a,b) a>b?a:b
using namespace std;
int main(){
int M,S,T;
scanf("%d %d %d",&M,&S,&T);
int linshi = 0,dist = 0; //中介路径,标准路径
for(int t = 1;t <=T;t++){
if(M>=10){
M = M-10;
linshi = linshi + 60;
}
else{
M = M+4;
}
dist = max(linshi,dist+17);
if(dist>= S){
printf("Yes\n%d\n",t);
break;
}
}
if(dist< S){
printf("No\n%d\n",dist);
}
}
贴上我初始复杂还不AC的代码= =
#include <stdio.h>
#include <string.h>
int main(){
int M,S,T; //魔法初值,距离S,时间T
scanf("%d %d %d",&M,&S,&T);
int linshi = 0; //路程
int i = 1; //常量
int cnt = 0;//记录时间
while(M>=10 && T>0){
M = M-10;
T--; //T每次在变
cnt++;
linshi = linshi + i*60;
if(linshi>=S){
printf("Yes\n%d\n",cnt);
break;
}
} //第一次循环结束,到补充能量时候
while( M>= 6 && M <= 9 && T>= 2){ //需要1s
T = T - 1;
cnt++;
M = M + 4;
while(M>=10 && T>0){
M = M-10;
T--;
cnt++;
linshi = linshi + i*60;
if(linshi>=S){
printf("Yes\n%d\n",cnt);
break;
}
}
}
while(M>= 2 && M <= 5 && T>= 3){ //需要2s
T = T - 2;
M = M + 8;
cnt = cnt+2;
while(M>=10 && T>0){
M = M-10;
T--;
cnt++;
linshi = linshi + i*60;
if(linshi>=S){
printf("Yes\n%d\n",cnt);
break;
}
}
}
while(M>= 0 && M <= 1 && T>= 7){ //需要3s //舍弃
T = T - 3;
M = M + 12;
cnt = cnt+3;
while(M>=10 && T>0){
M = M-10;
T--;
cnt++;
linshi = linshi + i*60;
if(linshi>=S){
printf("Yes\n%d\n",cnt);
break;
}
}
}
while(T>0 && T<4){ //还有时间,只能跑了
T--;
cnt++;
linshi = linshi + 17*i;
if(linshi>=S){
printf("Yes\n%d\n",cnt);
break;
}
}
printf("No\n%d\n",linshi); //没时间了
}