「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 }
相关文章
相关标签/搜索