Java中SPI的一些理解
題目描述
惡魔獵手尤迪安野心勃勃,他背叛了暗夜精靈,率領深藏在海底的娜迦族企圖叛變。守望者在與尤迪安的交鋒中遭遇了圍殺,被困在一個荒蕪的大島上。為了殺死守望者,尤迪安開始對這個荒島施咒,這座島很快就會沉下去。到那時,島上的所有人都會遇難。守望者的跑步速度為17m/s17m/s,以這樣的速度是無法逃離荒島的。慶幸的是守望者擁有閃爍法術,可在1s1s內移動60m60m,不過每次使用閃爍法術都會消耗魔法值1010點。守望者的魔法值恢復的速度為44點/s/s,只有處在原地休息狀態時才能恢復。
現在已知守望者的魔法初值MM,他所在的初始位置與島的出口之間的距離SS,島沉沒的時間TT。你的任務是寫一個程式幫助守望者計算如何在最短的時間內逃離荒島,若不能逃出,則輸出守望者在剩下的時間內能走的最遠距離。注意:守望者跑步、閃爍或休息活動均以秒(s)(s)為單位,且每次活動的持續時間為整數秒。距離的單位為米(m)(m)。
輸入格式
共一行,包括空格隔開的三個非負整數M, S, TM,S,T。
輸出格式
共兩行。
第11行為字串“YesYes”或“NoNo”(區分大小寫),即守望者是否能逃離荒島。
第22行包含一個整數。第一行為“YesYes”(區分大小寫)時表示守望者逃離荒島的最短時間;第一行為“NoNo”(區分大小寫)時表示守望者能走的最遠距離。
輸入輸出樣例
輸入 #1複製
39 200 4
輸出 #1複製
No 197
輸入 #2複製
36 255 10
輸出 #2複製
Yes 6
說明/提示
30%的資料滿足:1 \le T \le 10, 1 \le S \le 1001≤T≤10,1≤S≤100
50%的資料滿足:1 \le T < \le 1000, 1 \le S \le 100001≤T<≤1000,1≤S≤10000
100%的資料滿足:1 \le T \le 300000,0 \le M \le 1000, 1 \le S \le 10^81≤T≤300000,0≤M≤1000,1≤S≤108.
法一:貪心:
策略一:能閃就閃
策略二:普通走
兩種策略單獨進行,最後取最大。
#include <iostream> using namespace std; int main() { int m,s,t,l1=0,l2=0; cin>>m>>s>>t; for(int i=1; i<=t; i++){ l1+=17; if(m>=10){//能閃就閃 m-=10; l2+=60; } else m+=4; if(l2>l1)l1=l2;//閃的快一點就換成閃的 if(l1>=s){ cout<<"Yes"<<endl<<i<<endl; return 0; } } cout<<"No"<<endl<<l1<<endl; return 0; } //貪心思想,能閃就閃
法二: 動態規劃
#include <iostream>
using namespace std;
int dp[300005];//前i秒可以走多遠
int main()
{
int m,s,t;
cin>>m>>s>>t;
dp[0]=0;
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-1]+17,dp[i]);
if(dp[i]>=s){
cout<<"Yes"<<endl;
cout<<i<<endl;
return 0;
}
}
cout<<"No"<<endl<<dp[t]<<endl;
return 0;
}
/*必須將普通走路跟 閃回藍這兩種方式分開寫,假如寫在一個迴圈裡,如下:
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;
}
dp[i]=max(dp[i-1]+17,dp[i]);
if(dp[i]>=s){
cout<<"Yes"<<endl;
cout<<i<<endl;
return 0;
}
}
這是不行的,因為假如dp[i-1]+17>dp[i],即普通方式 > 閃回藍方式,普通走是不耗藍的,
但是前面的m卻變了,所以必須分開寫。
*/