167 条题解
- 
  5琀予 LV 8 @ 2017-10-15 11:32:29 根据题意,守望者要在最短时间走最多的路程,而每秒有三种方法:休息(魔法恢复4),跑步(移动十七米),闪烁法术(花费10魔法,移动60米)。可以得到如下信息: 
 1.休息和闪烁魔法是有关联的(要不然还不如不休息)。
 2.有魔法的情况下,尽量使用闪烁魔法(因为闪烁法术移动最远)。
 3.在魔法不够的情况下,对休息(等待魔法恢复使用闪烁法术)还是跑步进行选择。
 为了理清信息,不妨将跑步和使用闪烁法术分开处理。
 设想:
 1.如果守望者不会跑步,即第i秒的能到达最大距离为f[i],则:
 f[i]={f[i-1]+60 当m(魔法)>=10时,同时m=m-10
 f[i-1] 当m<10时,同时m=m+4
 通过这样一个预处理,解决了闪烁法术的使用。
 2.把跑步的情况加入,则:
 f[i]=MAX(f[i],f[i-1]+17) (注意:令f[0]=0)
 如此,得到了解决问题的递推式.当ft<S时,输出“No”及f[t]值,否则,就输出“Yes”及最快的离岛时间i。
 综合上述分析,具体实现步骤如下:
 1.读入数据M,S,T。
 2.计算只使用闪烁法术时的每秒最大距离。
 3.计算加入只使用跑步时的每秒最大距离,如果在某时刻刚好离岛,则输出离岛时间,结束。
 4.如果没有离岛,输出最远距离,结束。
 #include<iostream>
 using namespace std;
 long long m,s,t,i,f[500005];
 int main()
 {
 cin>>m>>s>>t;
 for(i=1;i<=t;i++)//循环时间
 {
 if(m>9)
 {
 f[i]=f[i-1]+60;
 m-=10; //闪现
 }
 else
 {
 f[i]=f[i-1];
 m+=4; //回蓝
 }
 }
 for(i=1;i<=t;i++)
 {
 if(f[i]<f[i-1]+17) f[i]=f[i-1]+17;//判断跑步
 if(f[i]>=s)
 {
 cout<<"Yes"<<endl;
 cout<<i<<endl;
 return 0;
 }
 }
 cout<<"No"<<endl<<f[t]<<endl;
 return 0;
 }
- 
  4@ 2017-08-07 11:20:37无数组无循环 #include<bits/stdc++.h> using namespace std; int m,s,t; int main() { //freopen("escape.in","r",stdin); //freopen("escape.out","w",stdout); int t0=0; int sum=0; scanf("%d%d%d",&m,&s,&t); int a=m/10; if(60*a>=s&&a<=t) { printf("Yes\n"); if(s%60==0) printf("%d\n",s/60); else printf("%d\n",s/60+1); return 0; } if(t<=a) { printf("No\n%d\n",60*t); return 0; } m=m-10*a; m=m/2*2; /* if((m==2||m==3||m==4||m==5)&&t>=a+3) { t=t-2; t0=t0+2; a=a+1; m=0; } if((m==6||m==7||m==8||m==9)&&t>=a+2) { t=t-1; t0=t0+1; a=a+1; m=0; }*/ if((m==2||m==4)&&t>=a+3) { t=t-2; t0=t0+2; a=a+1; m=m-2; } if((m==6||m==8)&&t>=a+2) { t=t-1; t0=t0+1; a=a+1; m=m-6; } if(60*a>=s&&a<=t) { printf("Yes\n"); if(s%60==0) printf("%d\n",s/60+t0); else printf("%d\n",s/60+1+t0); return 0; } if(m==2&&t>=a+3) { t=t-2; t0=t0+2; a=a+1; m=0; } if(m==6&&t>=a+2) { t=t-1; t0=t0+1; a=a+1; m=0; } if(60*a>=s&&a<=t) { printf("Yes\n"); if(s%60==0) printf("%d\n",s/60+t0); else printf("%d\n",s/60+1+t0); return 0; } t=t-a; t0=t0+a; sum=60*a; int smax=sum; int t1=t/7,t2=t-t1*7; smax=smax+t1*120+t2*17; if(smax<s) { printf("No\n%d\n",smax); return 0; } a=(s-sum)/120; int b; if(s-sum-a*120%17==0) b=(s-sum-a*120)/17; else b=(s-sum-a*120)/17+1; if(b>=7) { a=a+1; b=0; } t0=t0+a*7+b; printf("Yes\n%d\n",t0); return 0; }
- 
  2@ 2021-08-20 16:55:55#include<bits/stdc++.h> using namespace std; int main() { int quantity,s,time; cin>>quantity>>s>>time; int s1=0,s2=0,time1=time; while(s>s1 && time>0) { s1+=17; if(quantity>=10){ s2+=60; quantity-=10; } else quantity+=4; s1=max(s1,s2); time--; } if(s1<s) cout<<"No"<<"\n"<<s1; else cout<<"Yes"<<"\n"<<time1-time; return 0; }
- 
  1@ 2020-05-15 23:04:41#根据题意,守望者要在最短时间走最多的路程,而每秒有三种决策 ##我们不妨将跑步和使用闪烁法术分开处理 ###上代码 #include <cstdio> #include <algorithm> using namespace std; int dp[300001]; int main(){ int m,s,t; scanf("%d%d%d",&m,&s,&t); for(int i=1;i<=t;i++){//处理闪烁法术 if(m>=10)dp[i]=dp[i-1]+60,m-=10;//如果能用,就用 else dp[i]=dp[i-1],m+=4;//否则休息 } for(int i=1;i<=t;i++){dp[i]=max(dp[i],dp[i-1]+17);//处理跑步,dp[i]为使用法术和跑步的最大值(最优) if(dp[i]>=s){printf("Yes\n%d",i);return 0;}//如果超过了距离s,就成功了,输出yes }printf("No\n%d",dp[t]);//没成功,输出no return 0; }
- 
  1@ 2017-11-04 20:36:59//远离DP 
 var m,s,t,time,run,magic:longint;
 function find_max(x,y:longint):longint;
 begin
 if x>y then exit(x)
 else exit(y);
 end;
 begin
 readln(m,s,t);
 for time:=1 to t do
 begin
 if m>=10 then
 begin
 magic:=magic+60;
 m:=m-10;
 end
 else m:=m+4;
 run:=run+17;
 run:=find_max(run,magic);
 if run>=s then
 begin
 writeln('Yes');
 writeln(time);
 close(input);
 close(output);
 halt;
 end;
 end;
 writeln('No');
 writeln(run);
 end.
- 
  1@ 2017-09-11 21:44:26#include<iostream>//1172 
 #include<cstdio>
 #include<cmath>
 #include<cstring>
 #include<cstdlib>
 #include<algorithm>
 using namespace std;
 int m,n,s,ans,t,a[10001],b[10001],f[1000001];
 bool flag;
 int main()
 {
 cin>>m>>s>>t;
 for (int i=1;i<=t;i++)
 {
 if (m>=10)
 {
 f[i]=f[i-1]+60;
 m=m-10;
 }
 else
 {
 f[i]=f[i-1];
 m+=4;
 }
 }
 for (int i=1;i<=t;i++)
 f[i]=max(f[i],f[i-1]+17);
 for (int i=1;i<=t;i++)
 {
 if (f[i]>=s)
 {
 ans=i;
 flag=true;
 break;
 }
 if (i==t&&f[i]<s)
 {
 ans=f[i];
 flag=false;
 break;
 }
 }
 if (flag==true)
 cout<<"Yes"<<endl<<ans<<endl;
 else
 cout<<"No"<<endl<<ans<<endl;
 return 0;
 }
- 
  1@ 2017-09-10 15:03:05#include<iostream>//1172 
 #include<cstdio>
 #include<cmath>
 #include<cstring>
 #include<cstdlib>
 #include<algorithm>
 using namespace std;
 int m,s,t,x,y,i;
 int main()
 {
 cin>>m>>s>>t;
 for(int i=1;i<=t;i++)
 {
 x+=17;
 if(m>=10)
 {
 m-=10;
 y+=60;
 }
 else
 m+=4;
 if(x<y)
 x=y;
 if(x>=s)
 {
 cout<<"Yes"<<endl<<i;
 return 0;
 }
 }
 cout<<"No"<<endl<<x;
 return 0;
 }
- 
  1@ 2017-08-11 17:00:58dp解法 不可能把刷闪现和跑放在一起处理,所以分开两个循环做 
 ```cpp
 #include <iostream>
 #include <cstdio>
 #include <cstring>
 using namespace std;int magic,s,t,ans; 
 bool flag=false;
 int f[300001];int main() 
 {
 cin>>magic>>s>>t;for (int i=1;i<=t;i++){ //这一段纯粹刷闪现,有魔法就闪,没有就停下来补 
 if (magic>=10){
 f[i]=f[i-1]+60;
 magic-=10;
 }else{
 f[i]=f[i-1];
 magic+=4;
 }
 }for (int i=1;i<=t;i++){ //利用跑步,确定最优解 
 f[i]=max(f[i],f[i-1]+17);
 }for (int i=1;i<=t;i++){ //这后面的都是求解,没什么用 
 if (f[i]>=s){
 ans=i;
 flag=true;
 break;} 
 if (i==t && f[i]<s){
 ans=f[i];
 flag=false;
 }
 }if (flag){ 
 cout<<"Yes"<<endl<<ans<<endl;
 }else{
 cout<<"No"<<endl<<ans<<endl;
 }
 }
 ```
- 
  0@ 2021-07-13 12:08:29CCF书上有一模一样的题目 #include<iostream> #include<cstring> using namespace std; #define MAXN 300010 int main(){ int m,s,t,i; int f[MAXN]; cin>>m>>s>>t; f[0]=0; for(int i=1;i<=t;i++){//计算只用闪烁法术时的每秒最大距离 if(m>9)f[i]=f[i-1]+60,m-=10; else f[i]=f[i-1],m+=4; } for(int i=1;i<=t;i++){//计算加入跑步选择时的每秒最大距离 if(f[i]<f[i-1]+17)f[i]=f[i-1]+17; if(f[i]>=s){//刚好离岛 cout<<"Yes"<<endl<<i;return 0; } } cout<<"No"<<endl<<f[t];//不能离岛 return 0; }
- 
  0@ 2021-02-25 15:46:21#include<bits/stdc++.h> using namespace std; int m,s,t,now=0; int main() { cin>>m>>s>>t; int s1=0,s2=0; for(int i=1;i<=t;i++) { s1+=17; if(m>=10) {s2+=60; m-=10; } else m+=4; if(s2>s1) s1=s2; if(s1>s) { cout<<"Yes"<<endl<<i<<endl; return 0; } } cout<<"No"<<endl<<s1<<endl; }
- 
  0@ 2019-09-07 15:58:41这个贪心就行了吧 
- 
  0@ 2018-06-11 21:45:09/*此题dp,守望者有3个决策*/ #include<iostream> using namespace std; int m,s,t; int f[300005]; int main() { cin>>m>>s>>t; f[0]=0;//初始化 for (int i=1;i<=t;i++) { if (m>=10) {f[i]=f[i-1]+60;/*m>=10是表前一阶段+60*/m-=10;} //if (m<10) {f[i]=f[i-1]; m+=4;}阶段1s内只能有一个决策,用else; else {f[i]=f[i-1]; m+=4;} //守望者休息,恢复能量 } for (int i=1;i<=t;i++) { f[i]=max(f[i],f[i-1]+17);//DP if(f[i]>=s) {cout<<"Yes"<<endl<<i; return 0;} } cout<<"No"<<endl<<f[t]; return 0; }
- 
  0@ 2018-04-20 21:54:52**直接维护两个变量 x 和 y ,分别表示魔法值>=10 时候闪烁的距离x 和跑的距离y **每秒判断 x 和 y 的大小。若x >= y 就将y 的值更新为x **每秒判断 y 的大小和 S的差距,若T内能达到 y>=S,则输出yes和i;否则直接输出y的值 #include <iostream> 
 #include <cstdio>
 #include <functional>
 #include <vector>
 #include <algorithm>
 #include <queue>
 #include <stack>
 #include <cstring>
 #include <utility>
 #include <cstdlib>
 #include <cmath>#define LL long long #define MAX_N 110 
 #define INF 0x3f3f3f3f
 using namespace std;int M,S ,T; int main() 
 {
 cin >> M >> S >> T;
 int x = 0,y = 0;for(int i = 1;i <= T;i++){ 
 if( M >= 10 ){
 x+=60;
 M-=10;
 } else {
 x = x;
 M+=4;
 }
 y+=17;
 if(x >= y){
 y = x;
 }
 if(y >= S){
 cout << "Yes"<< endl;
 cout << i << endl;
 return 0;
 }
 }cout << "No" << endl; 
 cout << y << endl;
 return 0;
 }
- 
  0@ 2017-11-05 16:49:16#include<fstream> 
 #include<algorithm>
 using namespace std;
 int main()
 {
 int m,s,t;
 scanf("%d%d%d",&m,&s,&t);
 int a=0,b=0;
 for(int i=1;i<=t;i++)
 {
 a+=17;//跑步
 if(m>=10) //R闪
 {
 b+=60;
 m-=10;
 }
 else //break
 {
 m+=4;
 }
 if (a<b) a=b;//bigger
 if (a>s)
 {
 printf("Yes\n%d\n",i);
 return 0;
 }
 }
 if(a<s)
 {
 printf("No\n%d\n",a);
 return 0;
 }
 return 0;
 }
- 
  0@ 2017-11-03 21:08:11每步最优,远离DP 
 var m,s,t,time,run,magic:longint;
 function find_max(x,y:longint):longint;
 begin
 if x>y then exit(x)
 else exit(y);
 end;
 begin
 readln(m,s,t);
 for time:=1 to t do
 begin
 if m>=10 then
 begin
 magic:=magic+60;
 m:=m-10;
 end
 else m:=m+4;
 run:=run+17;
 run:=find_max(run,magic);
 if run>=s then
 begin
 writeln('Yes');
 writeln(time);
 close(input);
 close(output);
 halt;
 end;
 end;
 writeln('No');
 writeln(run);
 end.
- 
  0@ 2017-10-17 17:38:59var 
 m,s,t,x,y,i:longint;
 begin
 readln(m,s,t);
 for i:=1 to t do begin
 x:=x+17;
 if m>=10 then begin m:=m-10;y:=y+60;end
 else m:=m+4;
 if x<y then x:=y;
 if x>=s then begin writeln('Yes');writeln(i);exit;end;
 end;
 writeln('No');writeln(x);
 end.
- 
  0@ 2016-09-10 19:03:06简单贪心 
 var
 m,s,t,x,y,i:longint;
 begin
 readln(m,s,t);
 for i:=1 to t do begin
 x:=x+17;
 if m>=10 then begin m:=m-10;y:=y+60;end
 else m:=m+4;
 if x<y then x:=y;
 if x>=s then begin writeln('Yes');writeln(i);exit;end;
 end;
 writeln('No');writeln(x);
 end.
- 
  0@ 2016-09-03 16:44:00讲道理 这道题我一直不明觉厉 
 
 var
 m,s,t,s1,t1:int64;
 begin
 readln(m,s,t);
 s1:=s;
 t1:=t;
 while (t>0) and (s>0) do
 begin
 if m>=10 then
 begin
 m:=m-10;
 t:=t-1;
 s:=s-60;
 end
 else
 if (m>=6) and (t>=2) and (s>17) then
 begin
 m:=m+4;
 t:=t-1;
 end
 else
 if (m<6) and (m>=2) and (t>=3) and (s>51) then
 begin
 t:=t-2;
 m:=m+8;
 end
 else
 if (m<2) and (t>=7) and (s>119) then
 begin
 t:=t-5;
 m:=m+20;
 end
 else
 begin
 s:=s-17;
 t:=t-1;
 end;
 end;
 if s>0 then
 begin
 writeln('No');
 writeln(s1-s);
 end;
 if s<=0 then
 begin
 writeln('Yes');
 writeln(t1-t);
 end;
 end.
 
- 
  0@ 2016-08-02 11:29:04卡线Ac 
 测试数据 #0: Accepted, time = 968 ms, mem = 548 KiB, score = 10
 测试数据 #1: Accepted, time = 1000 ms, mem = 548 KiB, score = 10
 测试数据 #2: Accepted, time = 1000 ms, mem = 552 KiB, score = 10
 测试数据 #3: Accepted, time = 1000 ms, mem = 552 KiB, score = 10
 测试数据 #4: Accepted, time = 1000 ms, mem = 556 KiB, score = 10
 测试数据 #5: Accepted, time = 1000 ms, mem = 552 KiB, score = 10
 测试数据 #6: Accepted, time = 1000 ms, mem = 552 KiB, score = 10
 测试数据 #7: Accepted, time = 1000 ms, mem = 548 KiB, score = 10
 测试数据 #8: Accepted, time = 1000 ms, mem = 548 KiB, score = 10
 测试数据 #9: Accepted, time = 1000 ms, mem = 548 KiB, score = 10
 Accepted, time = 9968 ms, mem = 556 KiB, score = 100
 ```
 #ifndef _DEBUG#include <iostream> 
 #include <cstdio>
 #include <cstdlib>
 #include <memory>
 #include <vector>
 #include <string>
 #include <algorithm>
 #include <cmath>
 #include <queue>
 #include <cstring>
 #include <fstream>
 #include <cmath>
 #include <Windows.h>
 #include <iterator>
 #include <set>
 using namespace std;
 #endif // _DEBUGint main() { 
 int m, s, t;
 Sleep(985);
 scanf("%d%d%d", &m, &s, &t);
 int a=0, b=0,i;
 for (i = 1; i <= t; i++) {
 a += 17;
 if (m >= 10) { b += 60; m -= 10; }
 else { m += 4; }
 if (a < b)a = b;
 if (a > s) { printf("Yes\n%d\n", i); return 0; }} 
 if(a>s) { printf("Yes\n%d\n", i); return 0; }else { printf("No\n%d\n", a); return 0; }return 0; 
 }
 ```
- 
  0@ 2016-07-17 20:22:41不能就最后1次比较跑的和使用魔法哪个快,不考虑前面跑的 至少要比较后两次啊!!!!!! 
 (可证明,由于可能最后一次不能使用魔法,倒数第二次用魔法4s才走了60,普通走比不用魔法快,4s可走68,但2组魔法一起用一定比走快,所以是两次)
 否则第8个点过不去啊!
 后来写了个每次都比较魔法和走 就ac了