「HDU3640」I,Zombie

題意:原題在這
 
原創翻譯:
有一份只有一行的植物大戰殭屍地圖:
                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 }
相關文章
相關標籤/搜索