題意:原題在這
原創翻譯:
有一份只有一行的植物大戰殭屍地圖:
50hp的普通殭屍。
兩種植物:豌豆射手(10hp)和土豆雷(一次性)。
每秒的操做步驟以下:
1.在最右側的草皮中逐個放置0<=num的殭屍 (在最右邊草皮的右邊,即地圖以外)
2.判斷每個倖存的殭屍,是否站在一個豌豆射手身上:
if true,攻擊這個豌豆射手,豌豆射手hp -1.豌豆射手的hp在那一刻多是負值,但它仍然活着!
if false,向左移動一格。
3.若是地圖上還有殭屍,每個倖存的豌豆射手都會向最先放置的殭屍射擊(殭屍每被錘一下hp -1,殭屍的hp在那一刻多是負值,但它仍然活着!)
4.若是在土豆雷的草皮中有殭屍,那麼土豆雷爆炸,這個草皮中全部殭屍的hp變爲0。
5.非正hp的植物和殭屍消失(直到如今它們已經死亡)
請根據所給的地圖,求殭屍勝利的最小個數.
方法及思路:轉自:全網惟一一篇題解
模擬,主要有三個問題要維護,一是植物的長度,二是最右邊的植物種類,三是殭屍距離最近的植物的步數。
若是殭屍碰到了地雷,那麼下一回合能夠認爲殭屍的最左位置爲炸彈的左邊。(殭屍左移)
若是碰到的不是地雷,則不停向左統計植物個數,直到遇到第一個炸彈
而後二分能夠吃掉這些植物的最少殭屍個數,二分時要根據條件進行模擬。
其他詳見代碼註釋↓
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 int T; 8 int P,M,len,Zombie,Step; 9 char plant[150]; 10 11 void init(char p[]) 12 { 13 Zombie=P=M=0; 14 len=strlen(p)-1; 15 for(int i=0;i<=len;i++) 16 { 17 if(p[i]=='P') 18 P++; 19 else 20 M++; 21 } 22 } 23 24 int solve(int sum,int plnt,int zom)//植物總數,豌豆個數,殭屍個數 25 { 26 int flag=Step;//距離最近植物的步數 27 int plnt_life=10,zom_life=50;//初始生命值 28 while(plnt>0 && zom>0) 29 { 30 if(flag>0)//還沒到最近的植物 31 { 32 flag--;//走一步 33 zom_life-=sum;//這個殭屍會被全部植物錘 34 } 35 else//到了最近的植物 36 { 37 plnt_life-=zom;//這個豌豆會被全部殭屍錘 38 zom_life-=sum;//這個殭屍會被全部植物錘 39 } 40 if(plnt_life<=0)//死了一個射手 41 { 42 plnt_life=10; 43 sum--; plnt--; 44 flag=1; 45 } 46 if(zom_life<=0)//死了一個殭屍 47 { 48 zom_life=50; 49 zom--; 50 } 51 } 52 if(plnt<=0 && zom>0)//殭屍贏辣 53 return 1; 54 if(plnt<=0 && zom<=0)//都死光了 55 return 0; 56 if(plnt>0)//植物還活着 57 return -1; 58 } 59 60 int main() 61 { 62 cin>>T; 63 for(int cas=1;cas<=T;cas++) 64 { 65 cin>>plant; 66 init(plant); 67 if(plant[len]=='M')//有地雷 68 { 69 len--;//先犧牲一個殭屍玉石俱焚 70 Zombie++;//殭屍前進一步 71 Step=2; 72 } 73 else 74 Step=1; 75 while(len>=0)//只要還沒到brain處 76 { 77 if(plant[len]=='M')//前面是地雷 78 { 79 if(Step>1)//還沒到地雷 80 { 81 Step--;//走一步 82 if(P>=50) Zombie++;//而且打得過,那麼幹死一個殭屍 83 continue; 84 } 85 else 86 Zombie++;//死一個殭屍 87 M--; len--;//消耗一顆地雷 88 Step=2; 89 } 90 91 else//前面是豌豆射手 92 { 93 //從後往前統計豌豆個數 94 int pNum=0; 95 for(int i=len;i>=0;i--) 96 { 97 if(plant[i]=='M') 98 break; 99 else 100 pNum++; 101 } 102 //二分最少殭屍個數 103 int left=1,right=300,mid; 104 while(left<right)//直至二分出答案 105 { 106 mid=(left+right)>>1; 107 if(solve(P,pNum,mid)>0)//若是這種狀況下殭屍贏 108 right=mid; 109 else 110 left=mid+1; 111 } 112 Zombie+=left;//加上二分出的答案 113 P-=pNum; 114 len-=pNum+1; 115 Step=2; 116 } 117 } 118 if(plant[0]=='M')//判斷一開始是地雷 119 Zombie++; 120 printf("Case %d: %d\n",cas,Zombie); 121 } 122 return 0; 123 }