[Sdoi2010]猪国杀
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
[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>
5using namespace std;
6int top,thief,n,m,Left,king=1,zpre[11],znxt[11],dis[11][11];;
7char Card_heap[2005];
8bool like[11],dislike[11],simi_dislike[11];
9bool End;
10bool nanmanruqin(int) ;
11bool wanjianqifa(int) ;
12bool Kill(int,int) ;
13bool Lets_fight(int,int) ;
14char cread() {
15char ch=getchar();
16while(ch==32||ch==10||ch==13) ch=getchar();
17return ch;
18 }
19class PIG {
20private:
21int pre[2005],nxt[2005],tail;
22public:
23char Card[2005],identity[5];
24int id,kill,protect,peach,fight,AOEkill,AOEprotect,wuxiekeji,wuqi,life;
25bool equip,dead;
26void add(char ch) {
27if(ch=='P') ++peach;
28if(ch=='K') ++kill;
29if(ch=='D') ++protect;
30if(ch=='F') ++fight;
31if(ch=='N') ++AOEkill;
32if(ch=='W') ++AOEprotect;
33if(ch=='J') ++wuxiekeji;
34if(ch=='Z') ++wuqi;
35 }
36void write() {
37for(int j=nxt[0]; j<=tail; j=nxt[j]) {
38if(nxt[j]>tail) cout<<Card[j];
39else cout<<Card[j]<<"";
40 }
41 }
42void reduce(char ch) {
43if(ch=='P') --peach;
44if(ch=='K') --kill;
45if(ch=='D') --protect;
46if(ch=='F') --fight;
47if(ch=='N') --AOEkill;
48if(ch=='W') --AOEprotect;
49if(ch=='J') --wuxiekeji;
50if(ch=='Z') --wuqi;
51for(int i=nxt[0]; i<=tail; i=nxt[i]) {
52if(Card[i]==ch) {
53 pre[nxt[i]]=pre[i],nxt[pre[i]]=nxt[i];
54break;
55 }
56 }
57 }
58void init(int e) {
59 scanf("%s",identity);
60 equip=false,life=4,id=e;
61 kill=protect=peach=AOEkill=AOEprotect=wuxiekeji=wuqi=0;
62for(int i=1; i<=4; ++i) Card[++tail]=cread(),add(Card[tail]);
63for(int i=0; i<=2000; ++i) pre[i]=i-1,nxt[i]=i+1;
64 }
65void take_card(int num) {
66int i;
67for(i=1; i<=num&&top<m; ++i) Card[++tail]=Card_heap[++top],add(Card[tail])/*,cout<<Card[tail]<<" "*/; 68if(i<=num) for( ; i<=num; ++i) Card[++tail]=Card_heap[top],add(Card[tail])/*,cout<<Card[tail]<<" "*/;
69 }
70void punish() {
71 nxt[0]=tail+1;
72 pre[tail+1]=0;
73 equip=kill=protect=peach=AOEkill=AOEprotect=wuxiekeji=wuqi=0;
74 }
75bool eat_peach() {
76if(life==4||!peach) return false;
77 ++life,reduce('P');
78return true;
79 }
80void Equip() {
81if(!wuqi) return ;
82 reduce('Z'),equip=true;
83 }
84bool action() {
85bool used_kill=false;
86while(true) {
87bool if_action=false;
88for(int i=nxt[0]; i<=tail; i=nxt[i]) {
89if(life<=0) {if_action=false; break;}
90if(Card[i]=='N') {
91 reduce(Card[i]);
92bool now=nanmanruqin(id);
93if(now) return true;
94 if_action=true;
95break;
96 }
97if(Card[i]=='W') {
98 reduce(Card[i]);
99bool now=wanjianqifa(id);
100if(now) return true;
101 if_action=true;
102break;
103 }
104if(Card[i]=='P') {
105 eat_peach();
106continue;
107 }
108if(Card[i]=='Z') {
109 Equip();
110 if_action=true;
111break;
112 }
113if(Card[i]=='K') {
114if(!used_kill||equip) {
115bool now=false;
116if(identity[0]=='M'&&(dislike[znxt[id]]||simi_dislike[znxt[id]])) {
117 now=Kill(id,znxt[id]);
118if(now) return true;
119 used_kill=if_action=true;
120break;
121 }
122if(identity[0]=='Z'&&dislike[znxt[id]]) {
123 now=Kill(id,znxt[id]);
124if(now) return true;
125 used_kill=if_action=true;
126break;
127 }
128if(identity[0]=='F'&&(like[znxt[id]]||znxt[id]==1)) {
129 now=Kill(id,znxt[id]);
130if(now) return true;
131 used_kill=if_action=true;
132break;
133 }
134 }
135continue;
136 }
137if(Card[i]=='F') {
138if(identity[0]=='M') {
139int ji=0;
140for(int i=znxt[id]; i!=id; i=znxt[i]) {
141if(dislike[i]||simi_dislike[i]) {
142 ji=i;
143break;
144 }
145 }
146if(ji!=0) {
147bool now=Lets_fight(id,ji);
148if(now) return true;
149 if_action=true;
150break;
151 }
152continue;
153 }
154if(identity[0]=='Z') {
155int ji=0;
156for(int i=znxt[id]; i!=id; i=znxt[i]) if(dislike[i]) {
157 ji=i;
158break;
159 }
160if(ji!=0) {
161bool now=Lets_fight(id,ji);
162if(now) return true;
163 if_action=true;
164break;
165 }
166continue;
167 }
168if(identity[0]=='F') {
169bool now=Lets_fight(id,1);
170if(now) return true;
171 if_action=true;
172break;
173 }
174 }
175 }
176if(if_action) continue;
177else break;
178 }
179return false;
180 }
181 } pig[11];
182
183
184void divide_dis() {
185 memset(dis,0x5f,sizeof(dis));
186int ji=0;
187for(register int i=1,now=0; i<=n; i=znxt[i],now=0) {
188if(i==1&&!ji) ++ji;
189if(i==1&&ji) break;
190for(register int j=znxt[i]; j<=n; ++j) dis[i][j]=++now,dis[j][i]=Left-now;
191 }
192 }
193int If_end() {
194if(!king) return1;
195if(!thief) return2;
196return0;
197 }
198bool Be_killed(int who,int who_kill) {
199if(pig[who].life>0) return false;
200 --Left,pig[who].dead=true;
201if(pig[who].identity[0]=='M') --king;
202if(pig[who].identity[0]=='F') --thief;
203if(If_end()) {
204 End=true;
205return true;
206 }
207if(pig[who].identity[0]=='F') pig[who_kill].take_card(3);
208if(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();
211return false;
212 }
213void Start_init() {
214 scanf("%d%d",&n,&m);
215 Left=n;
216for(int i=1; i<=n; ++i) {
217 pig[i].init(i);
218if(pig[i].identity[0]=='F') ++thief;
219 }
220for(int i=1; i<=n; ++i) zpre[i]=i-1,znxt[i]=i+1;
221 znxt[n]=1,zpre[1]=n;
222 divide_dis();
223for(int i=1; i<=m; ++i) Card_heap[i]=cread();
224 }
225bool love(int fr,int to) {
226if(pig[fr].identity[0]=='Z'&&(pig[to].id==1||like[to])) return true;
227if(pig[fr].id==1&&(like[to]||pig[to].id==1)) return true;
228if(pig[fr].identity[0]=='F'&&dislike[to]) return true;
229return false;
230 }
231bool hate(int fr,int to) {
232if(pig[fr].identity[0]=='F'&&(pig[to].id==1||like[to])) return true;
233if(pig[fr].id==1&&dislike[to]) return true;
234if(pig[fr].identity[0]=='Z'&&dislike[to]) return true;
235return false;
236 }
237void make(int fr) {
238if(pig[fr].identity[0]=='Z') like[fr]=true,dislike[fr]=false,simi_dislike[fr]=false;
239if(pig[fr].identity[0]=='F') like[fr]=false,dislike[fr]=true,simi_dislike[fr]=false;
240 }
241bool wuxie(int now,int to,bool sta) { // 1 被攻击 0 已经被⽆懈
242if(!like[to]&&!dislike[to]&&pig[to].id!=1) return0;
243for(int i=now,bo=0; i!=now||bo==0; i=znxt[i]) {
244 bo=1;
245if(!pig[i].wuxiekeji) continue;
246if(love(i,to)&&sta) {make(i);pig[i].reduce('J');return wuxie(znxt[i],i,0)^1;} 247if(hate(i,to)&&!sta) {make(i);pig[i].reduce('J');return wuxie(znxt[i],i,0)^1;} 248 }
249return0;
250 }
251int main() {
252 Start_init();
253for(int i=1,ji=1; !End; i=znxt[i],++ji) {
254 pig[i].take_card(2);
255 pig[i].action();
256 }
257if(If_end()==1) printf("FP\n");
258else printf("MP\n");
259for(int i=1; i<=n; ++i,printf("\n")) {
260if(pig[i].dead) printf("DEAD");
261else pig[i].write();
262 }
263return0;
264 }
265
266bool nanmanruqin(int who_use) {
267for(int i=znxt[who_use]; i!=who_use; i=znxt[i]) {
268if(wuxie(who_use,i,true)) continue;
269if(!pig[i].kill) {
270 --pig[i].life;
271if(!pig[i].life) {
272if(!pig[i].eat_peach())
273if(Be_killed(i,who_use))return true;
274 }
275if(i==1) simi_dislike[who_use]=true;
276 }
277if(pig[i].kill) pig[i].reduce('K');
278 }
279return false;
280 }
281bool wanjianqifa(int who_use) {
282for(int i=znxt[who_use]; i!=who_use; i=znxt[i]) {
283if(wuxie(who_use,i,true)) continue;
284if(!pig[i].protect) {
285 --pig[i].life;
286if(!pig[i].life) {
287if(!pig[i].eat_peach()) {
288if(Be_killed(i,who_use))return true;
289 }
290 }
291if(i==1) simi_dislike[who_use]=true;
292 } else pig[i].reduce('D');
293 }
294return false;
295 }
296bool Kill(int fr,int to) {
297 pig[fr].reduce('K');
298if(!pig[to].protect) {
299 --pig[to].life;
300if(!pig[to].life) {
301if(!pig[to].eat_peach()) {
302bool now=Be_killed(to,fr);
303if(now) {
304 End=true;
305return true;
306 }
307 }
308 }
309 } else pig[to].reduce('D');
310if(pig[to].identity[0]=='M'||like[to]) dislike[fr]=true;
311if(dislike[to]) like[fr]=true;
312return false;
313 }
314bool Lets_fight(int fr,int to) {
315if(pig[to].id==1||like[to]) dislike[fr]=true;
316if(dislike[to]) like[fr]=true;
317 pig[fr].reduce('F');
318if(wuxie(fr,to,true)) return false;
319if((fr==1&&pig[to].identity[0]=='Z')) {
320 --pig[to].life;
321if(!pig[to].life) if(!pig[to].eat_peach()) Be_killed(to,fr);
322return false;
323 }
324int now=1;
325while(true) {
326int dd=now?to:fr;
327if(pig[dd].kill) {
328 pig[dd].reduce('K');
329 now^=1;
330continue;
331 }
332if(!pig[dd].kill) {
333 --pig[dd].life;
334if(!pig[dd].life) {
335if(pig[dd].eat_peach()) break;
336else {
337bool ss=Be_killed(dd,dd==fr?to:fr); 338if(ss) return true;
339 }
340 }
341break;
342 }
343 now^=1;
344 }
345return false;
346 }
View Code。