[Sdoi2010]猪国杀

概述
 
 
《猪国杀》是一种多猪牌类回合制游戏,一共有三种角色:主猪,忠猪,反猪。
每局游戏主猪有且只有一只,忠猪和反猪可以有多只,每只猪扮演一种角色。
 
游戏目的
 
主猪(MP):自己存活的情况下消灭所有的反猪。
忠猪(ZP):不惜一切保护主猪,胜利条件与主猪相同。
反猪(AP):杀死主猪。
 
 
游戏过程
 
 
游戏开始时候,每个玩家手里都会有 4 张牌,且体力上限和初始体力都是 4 。
开始游戏时,从主猪开始,按照逆时针方向(数据中就是按照编号从 1, 2, 3...n, 1... 的顺序)依次行动。
每个玩家自己的回合可以分为 4 个阶段
 
 
摸牌阶段
 
从牌堆顶部摸两张牌,依次放到手牌的最右边。
 
 
出牌阶段
 
你可以使用 0 张到任意张牌,每次使用牌的时候都使用最靠左的能够使用的牌。
当然,要满足如下规则
 
如果没有猪哥连弩,每个出牌阶段只能使用一次“杀”来攻击。
任何牌被使用后被弃置(武器是装备上)。
被弃置的牌以后都不能再用,即与游戏无关。
 
 
各种牌介绍
 
每张手牌用一个字母表示,字母代表牌的种类。
 
 
基本牌
 
『桃(P)』
 
在自己的回合内,如果自己的体力值不等于体力上限,那么使用一个桃可以为自己补充一点体力;否则不能使用桃。
桃只能对自己使用。
在自己的回合外,如果自己的血变为 0 或者更低,那么也可以使用。
 
 
『杀(K)』
 
在自己的回合内,对攻击范围内除自己以外的一名角色使用。
如果没有被『闪』抵消,则造成 1 点伤害。
无论有无武器,杀的攻击范围都是 1。
 
 
『闪(D)』
 
当你受到杀的攻击时,可以弃置一张闪来抵消杀的效果。
 
 
锦囊牌
 
 
『决斗(F)』
 
出牌阶段,对除自己以外任意一名角色使用,由目标角色先开始,自己和目标角色轮流弃置一张杀,首先没有杀可弃的一方受到1点伤害,另一方视为此伤害的来源。
 
 
『南猪入侵(N)』
 
出牌阶段,对除你以外所有角色使用,按逆时针顺序从使用者下家开始依次结算,除非弃置一张杀,否则受到1点伤害。
 
 
『万箭齐发(W)』
 
和南猪入侵类似,不过要弃置的不是杀而是闪。
 
 
『无懈可击(J)』
 
在目标锦囊生效前抵消其效果。
每次有一张锦囊即将生效时,从使用这张锦囊的猪开始,按照逆时针顺序,依次得到使用无懈可击的机会。
 
效果
 
用于决斗时,决斗无效并弃置。
用于南猪入侵或万箭齐发时,当结算到某个角色时才能使用,当前角色不需弃置牌并且不会受到伤害(仅对一个角色产生效果)。
用于无懈可击时,成为目标的无懈可击被无效。
 
 
装备牌
 
 
『猪哥连弩(Z)』
 
 
武器,攻击范围 1,出牌阶段你可以使用任意张杀。
 
同一时刻最多只能装一个武器。
如果先前已经有了一把武器,那么之后再装武器的话,会弃置以前的武器来装现在的武器。
 
 
 
特殊事件及概念解释
 
伤害来源
 
杀、南猪入侵、万箭齐发的伤害来源均是使用该牌的猪。
决斗的伤害来源如上。
 
 
距离
 
两只猪的距离定义为沿着逆时针方向间隔的猪数 +1。即初始时 1 和 2 的距离为 1 ,但是 2 和 1 的距离就是 n - 1 。
注意一个角色的死亡会导致一些猪距离的改变。
 
 
玩家死亡
 
如果该玩家的体力降到 0 或者更低,并且自己手中没有足够的桃使得自己的体力值回到 1,那么就死亡了,死亡后所有的牌(装备区,手牌区)被弃置、
 
 
奖励与惩罚
 
反猪死亡时,最后一个伤害来源处(即使是反猪)立即摸三张牌。
忠猪死亡时,如果最后一个伤害来源是主猪,那么主猪所有装备牌、手牌被弃置。
注意,一旦达成胜利条件,游戏立刻结束,因此即使会摸 3 张牌或者还有牌可以用也不用执行了。
现在,我们已经知道每只猪的角色、手牌,还有牌堆初始情况,并且假设每个角色会按照如下的行为准则进行游戏,你需要做的就是告诉小猪 iPig 最后的结果。
 
 
几种行为
 
献殷勤
 
使用无懈可击挡下南猪入侵、万箭齐发、决斗。
使用无懈可击抵消表敌意。
 
表敌意
 
对某个角色使用杀、决斗。
使用无懈可击抵消献殷勤。
 
跳忠
 
即通过行动表示自己是忠猪。
跳忠行动就是对主猪或对某只已经跳忠的猪献殷勤,或者对某只已经跳反的猪表敌意。
 
 
跳反
 
即通过行动表示自己是反猪。
跳反行动就是对主猪或对某只已经跳忠的猪表敌意,或者对某只已经跳反的猪献殷勤。
忠猪不会跳反,反猪也不会跳忠。
不管是忠猪还是反猪,能够跳必然跳。
 
 
行动准则
共性
 
每个角色如果手里有桃且生命值未满,那么必然吃掉。
有南猪入侵、万箭齐发、必然使用。
有装备必然装上。
受到杀时,有闪必然弃置。
响应南猪入侵或者万箭齐发时候,有杀/闪必然弃置。
不会对未表明身份的猪献殷勤(包括自己)。
 
 
特性
 
主猪
 
主猪会认为没有跳身份,且用南猪入侵/万箭齐发对自己造成伤害的猪是“类反猪”(没伤害到不算,注意“类反猪”并没有表明身份),如果之后跳了,那么主猪会重新认识这只猪。
对于每种表敌意的方式,对逆时针方向能够执行到的第一只“类反猪”或者已跳反猪表;如果没有,那么就不表敌意。
决斗时会不遗余力弃置杀。
如果能对已经跳忠的猪或自己献殷勤,那么一定献。
如果能够对已经跳反的猪表敌意,那么一定表。
 
忠猪
 
对于每种表敌意的方式,对逆时针方向能够执行到的第一只已经跳反的猪表;如果没有,那么就不表敌意。
决斗时,如果对方是主猪,那么不会弃置杀,否则,会不遗余力弃置杀。
如果有机会对主猪或者已经跳忠的猪献殷勤,那么一定献。
 
反猪
 
对于每种表敌意的方式,如果有机会则对主猪表,否则,对逆时针方向能够执行到的第一只已经跳忠的猪表;如果没有,那么就不表敌意。
决斗时会不遗余力弃置杀。
如果有机会对已经跳反的猪献殷勤,那么一定献。
 
 
限于 iPig 只会用 P++ 语言写 A + B,他请你用 Pigcal(Pascal)、P(C) 或 P++(C++) 语言来帮他预测最后的结果。
solution:
  没什么说的,恶心大模拟,一堆坑点,码力太弱.......
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 int top,thief,n,m,Left,king=1,zpre[11],znxt[11],dis[11][11];;
  7 char Card_heap[2005];
  8 bool like[11],dislike[11],simi_dislike[11];
  9 bool End;
 10 bool nanmanruqin(int) ;
 11 bool wanjianqifa(int) ;
 12 bool Kill(int,int) ;
 13 bool Lets_fight(int,int) ;
 14 char cread() {
 15     char ch=getchar();
 16     while(ch==32||ch==10||ch==13) ch=getchar();
 17     return ch;
 18 }
 19 class PIG {
 20     private:
 21         int pre[2005],nxt[2005],tail;
 22     public:
 23         char Card[2005],identity[5];
 24         int id,kill,protect,peach,fight,AOEkill,AOEprotect,wuxiekeji,wuqi,life;
 25         bool equip,dead;
 26         void add(char ch) {
 27             if(ch=='P') ++peach;
 28             if(ch=='K') ++kill;
 29             if(ch=='D') ++protect;
 30             if(ch=='F') ++fight;
 31             if(ch=='N') ++AOEkill;
 32             if(ch=='W') ++AOEprotect;
 33             if(ch=='J') ++wuxiekeji;
 34             if(ch=='Z') ++wuqi;
 35         }
 36         void write() {
 37             for(int j=nxt[0]; j<=tail; j=nxt[j]) {
 38                 if(nxt[j]>tail) cout<<Card[j];
 39                 else cout<<Card[j]<<" ";
 40             }
 41         }
 42         void reduce(char ch) {
 43             if(ch=='P') --peach;
 44             if(ch=='K') --kill;
 45             if(ch=='D') --protect;
 46             if(ch=='F') --fight;
 47             if(ch=='N') --AOEkill;
 48             if(ch=='W') --AOEprotect;
 49             if(ch=='J') --wuxiekeji;
 50             if(ch=='Z') --wuqi;
 51             for(int i=nxt[0]; i<=tail; i=nxt[i]) {
 52                 if(Card[i]==ch) {
 53                     pre[nxt[i]]=pre[i],nxt[pre[i]]=nxt[i];
 54                     break;
 55                 }
 56             }
 57         }
 58         void init(int e) {
 59             scanf("%s",identity);
 60             equip=false,life=4,id=e;
 61             kill=protect=peach=AOEkill=AOEprotect=wuxiekeji=wuqi=0;
 62             for(int i=1; i<=4; ++i) Card[++tail]=cread(),add(Card[tail]);
 63             for(int i=0; i<=2000; ++i) pre[i]=i-1,nxt[i]=i+1;
 64         }
 65         void take_card(int num) {
 66             int i;
 67             for(i=1; i<=num&&top<m; ++i) Card[++tail]=Card_heap[++top],add(Card[tail])/*,cout<<Card[tail]<<" "*/;
 68             if(i<=num) for( ; i<=num; ++i) Card[++tail]=Card_heap[top],add(Card[tail])/*,cout<<Card[tail]<<" "*/;
 69         }
 70         void punish() {
 71             nxt[0]=tail+1;
 72             pre[tail+1]=0;
 73             equip=kill=protect=peach=AOEkill=AOEprotect=wuxiekeji=wuqi=0;
 74         }
 75         bool eat_peach() {
 76             if(life==4||!peach) return false;
 77             ++life,reduce('P');
 78             return true;
 79         }
 80         void Equip() {
 81             if(!wuqi) return ;
 82             reduce('Z'),equip=true;
 83         }
 84         bool action() {
 85             bool used_kill=false;
 86             while(true) {
 87                 bool if_action=false;
 88                 for(int i=nxt[0]; i<=tail; i=nxt[i]) {
 89                     if(life<=0) {if_action=false; break;}
 90                     if(Card[i]=='N') {
 91                         reduce(Card[i]);
 92                         bool now=nanmanruqin(id);
 93                         if(now) return true;
 94                         if_action=true;
 95                         break;
 96                     }
 97                     if(Card[i]=='W') {
 98                         reduce(Card[i]);
 99                         bool now=wanjianqifa(id);
100                         if(now) return true;
101                         if_action=true;
102                         break;
103                     }
104                     if(Card[i]=='P') {
105                         eat_peach();
106                         continue;
107                     }
108                     if(Card[i]=='Z') {
109                         Equip();
110                         if_action=true;
111                         break;
112                     }
113                     if(Card[i]=='K') {
114                         if(!used_kill||equip) {
115                             bool now=false;
116                             if(identity[0]=='M'&&(dislike[znxt[id]]||simi_dislike[znxt[id]])) {
117                                 now=Kill(id,znxt[id]);
118                                 if(now) return true;
119                                 used_kill=if_action=true;
120                                 break;
121                             }   
122                             if(identity[0]=='Z'&&dislike[znxt[id]]) {
123                                 now=Kill(id,znxt[id]);
124                                 if(now) return true;
125                                 used_kill=if_action=true;
126                                 break;
127                             }
128                             if(identity[0]=='F'&&(like[znxt[id]]||znxt[id]==1)) {
129                                 now=Kill(id,znxt[id]);
130                                 if(now) return true;
131                                 used_kill=if_action=true;
132                                 break;
133                             }
134                         }
135                         continue;
136                     }
137                     if(Card[i]=='F') {
138                         if(identity[0]=='M') {
139                             int ji=0;
140                             for(int i=znxt[id]; i!=id; i=znxt[i]) {
141                                 if(dislike[i]||simi_dislike[i]) {
142                                     ji=i;
143                                     break;
144                                 }
145                             }
146                             if(ji!=0) {
147                                 bool now=Lets_fight(id,ji);
148                                 if(now) return true;
149                                 if_action=true;
150                                 break;
151                             } 
152                             continue;
153                         }
154                         if(identity[0]=='Z') {
155                             int ji=0;
156                             for(int i=znxt[id]; i!=id; i=znxt[i]) if(dislike[i]) {
157                                 ji=i;
158                                 break;
159                             }
160                             if(ji!=0) {
161                                 bool now=Lets_fight(id,ji);
162                                 if(now) return true;
163                                 if_action=true;
164                                 break;
165                             } 
166                             continue;
167                         }
168                         if(identity[0]=='F') {
169                             bool now=Lets_fight(id,1);
170                             if(now) return true;
171                             if_action=true;
172                             break;
173                         }
174                     }
175                 }
176                 if(if_action) continue;
177                 else break;
178             }
179             return false;
180         }
181 } pig[11];
182   
183   
184 void divide_dis() {
185     memset(dis,0x5f,sizeof(dis));
186     int ji=0;
187     for(register int i=1,now=0; i<=n; i=znxt[i],now=0) {
188         if(i==1&&!ji) ++ji;
189         if(i==1&&ji) break;
190         for(register int j=znxt[i]; j<=n; ++j) dis[i][j]=++now,dis[j][i]=Left-now;
191     }
192 }
193 int If_end() {
194     if(!king) return 1;
195     if(!thief) return 2;
196     return 0;
197 }
198 bool Be_killed(int who,int who_kill) {
199     if(pig[who].life>0) return false;
200     --Left,pig[who].dead=true;
201     if(pig[who].identity[0]=='M') --king;
202     if(pig[who].identity[0]=='F') --thief;
203     if(If_end()) {
204         End=true;
205         return true;
206     }
207     if(pig[who].identity[0]=='F') pig[who_kill].take_card(3);
208     if(pig[who].identity[0]=='Z'&&pig[who_kill].identity[0]=='M') pig[who_kill].punish();
209     zpre[znxt[who]]=zpre[who],znxt[zpre[who]]=znxt[who];
210     divide_dis();
211     return false;
212 }
213 void Start_init() {
214     scanf("%d%d",&n,&m);
215     Left=n;
216     for(int i=1; i<=n; ++i) {
217         pig[i].init(i);
218         if(pig[i].identity[0]=='F') ++thief;
219     }
220     for(int i=1; i<=n; ++i) zpre[i]=i-1,znxt[i]=i+1;
221     znxt[n]=1,zpre[1]=n;
222     divide_dis();
223     for(int i=1; i<=m; ++i) Card_heap[i]=cread();
224 }
225 bool love(int fr,int to) {
226     if(pig[fr].identity[0]=='Z'&&(pig[to].id==1||like[to])) return true;
227     if(pig[fr].id==1&&(like[to]||pig[to].id==1)) return true;
228     if(pig[fr].identity[0]=='F'&&dislike[to]) return true;
229     return false;
230 }
231 bool hate(int fr,int to) {
232     if(pig[fr].identity[0]=='F'&&(pig[to].id==1||like[to])) return true;
233     if(pig[fr].id==1&&dislike[to]) return true;
234     if(pig[fr].identity[0]=='Z'&&dislike[to]) return true;
235     return false;
236 }
237 void make(int fr) {
238     if(pig[fr].identity[0]=='Z') like[fr]=true,dislike[fr]=false,simi_dislike[fr]=false;
239     if(pig[fr].identity[0]=='F') like[fr]=false,dislike[fr]=true,simi_dislike[fr]=false;
240 }
241 bool wuxie(int now,int to,bool sta) { // 1 被攻击 0 已经被无懈 
242     if(!like[to]&&!dislike[to]&&pig[to].id!=1) return 0;
243     for(int i=now,bo=0; i!=now||bo==0; i=znxt[i]) {
244         bo=1;
245         if(!pig[i].wuxiekeji) continue;
246         if(love(i,to)&&sta) {make(i);pig[i].reduce('J');return wuxie(znxt[i],i,0)^1;}
247         if(hate(i,to)&&!sta) {make(i);pig[i].reduce('J');return wuxie(znxt[i],i,0)^1;}
248     }
249     return 0;
250 }
251 int main() {
252     Start_init();
253     for(int i=1,ji=1; !End; i=znxt[i],++ji) {
254         pig[i].take_card(2);
255         pig[i].action();
256     }
257     if(If_end()==1) printf("FP\n");
258     else printf("MP\n");
259     for(int i=1; i<=n; ++i,printf("\n")) {
260         if(pig[i].dead) printf("DEAD");
261         else pig[i].write();
262     }
263     return 0;
264 }
265   
266 bool nanmanruqin(int who_use) {
267     for(int i=znxt[who_use]; i!=who_use; i=znxt[i]) {
268         if(wuxie(who_use,i,true)) continue;
269         if(!pig[i].kill) {
270             --pig[i].life;
271             if(!pig[i].life) {
272                 if(!pig[i].eat_peach())
273                     if(Be_killed(i,who_use))return true;
274             }
275             if(i==1) simi_dislike[who_use]=true;
276         }
277         if(pig[i].kill) pig[i].reduce('K');
278     }
279     return false;
280 }
281 bool wanjianqifa(int who_use) {
282     for(int i=znxt[who_use]; i!=who_use; i=znxt[i]) {
283         if(wuxie(who_use,i,true)) continue;
284         if(!pig[i].protect) {
285             --pig[i].life;
286             if(!pig[i].life) {
287                 if(!pig[i].eat_peach()) {
288                     if(Be_killed(i,who_use))return true;
289                 }
290             }
291             if(i==1) simi_dislike[who_use]=true;
292         } else pig[i].reduce('D');
293     }
294     return false;
295 }
296 bool Kill(int fr,int to) {
297     pig[fr].reduce('K');
298     if(!pig[to].protect) {
299         --pig[to].life;
300         if(!pig[to].life) {
301             if(!pig[to].eat_peach()) {
302                 bool now=Be_killed(to,fr);
303                 if(now) {
304                     End=true;
305                     return true;
306                 }
307             }
308         }
309     } else pig[to].reduce('D');
310     if(pig[to].identity[0]=='M'||like[to]) dislike[fr]=true;
311     if(dislike[to]) like[fr]=true;
312     return false;
313 }
314 bool Lets_fight(int fr,int to) {
315     if(pig[to].id==1||like[to]) dislike[fr]=true;
316     if(dislike[to]) like[fr]=true;
317     pig[fr].reduce('F');
318     if(wuxie(fr,to,true)) return false;
319     if((fr==1&&pig[to].identity[0]=='Z')) {
320         --pig[to].life;
321         if(!pig[to].life) if(!pig[to].eat_peach()) Be_killed(to,fr);
322         return false;
323     }
324     int now=1;
325     while(true) {
326         int dd=now?to:fr;
327         if(pig[dd].kill) {
328             pig[dd].reduce('K');
329             now^=1;
330             continue;
331         }
332         if(!pig[dd].kill) {
333             --pig[dd].life;
334             if(!pig[dd].life) {
335                 if(pig[dd].eat_peach()) break;
336                 else {
337                     bool ss=Be_killed(dd,dd==fr?to:fr);
338                     if(ss) return true;
339                 }
340             }
341             break;
342         }
343         now^=1;
344     }
345     return false;
346 }
View Code

 

posted @ 2017-10-16 08:03  Forever_goodboy  阅读(2701)  评论(0编辑  收藏  举报