洛谷P2482 [SDOI2010]猪国杀——题解
猪国杀,模拟题的一颗耀眼的明珠,成长大牛、锻炼码力必写题!
模拟题没什么思维难度。只要按部就班地去做就是。模拟简单在这,难也在这。因为题面巨长,条件巨多,忽疏一点都有可能全盘皆输。故推荐考试时碰见了,除非真的闲的没事,否则尽量不要碰。一旦陷入细节混乱的深渊,估计一上午/下午的考试就混过去了。
总结一下做题的注意点:
1、审题是最基本的!
做大模拟题时,必须要认真读题,可能的话,要把所有条件都列举出来(不然就会像我一样,调了一上午才发现就是忘了几个题目中提到的条件或要求)。
2、理清思路。
不要吝啬草稿纸,把框架、注意点都写出来。相信我,除非您是AKIOI/NOI/CSP很强的大佬,否则在敲了几百行代码后,肯定会忘了些什么的。而忘了的,都会成为事后艰难调试的根源之一。
同时,写代码时推荐多利用自定义函数,变量名尽量都用自己熟悉的、见名知意的。这样不仅使程序层次清晰、易于理解,还方便后期的调试(不然写了500行代码后再回来看a1,a2..什么的自己都不知道意义的变量,想死的心都有了)
3、对于本题来说,找准对象、明确不同对象之间行为的差别也是很有必要的。这种细节特别容易忘,而找起来不留意的话也很难找。
接下来说一下我犯过的容易掉的坑吧,注意一下,这也算是这片题解的主体(没准您就掉进这些坑中呢?):
1、杀死反猪后会摸牌,要注意猪能否再出牌
2、 反猪决斗优先打主公(读题)
3、决斗可能会自杀
4、决斗只能在第一个人出杀前被无懈可击掉
5、要注意用牌的顺序(从左到右),以便输出
6、杀、决斗、无懈可击都会标明身份,南猪入侵和万箭齐发顶多在未表明身份时被主猪认为类反贼
7、决斗时,主公认为对面是类反贼,实际上是忠臣的情况下,忠臣要牺牲一滴血(连无懈可击也不能出)
8、当自己没表明身份时,不能对自己用无懈可击
9、牌能用,要先把用牌的标记打上,免得主杀忠弃牌后再打标记导致错误
10、装上猪哥连弩有可能使前面的杀能用
11、中途有新的猪表明身份后,也有可能能让前面的决斗或杀能用。
12、要每次都用最左边的能用的牌,是对全体来说,而不是对某种来说!
13、“无懈可击:在目标锦囊生效前抵消其效果。每次有一张锦囊即将生效时,从使用这张锦囊的猪开始,按照逆时针顺序,依次得到使用无懈可击的机会”。这一点与三国杀不同,三国杀是从锦囊牌的对象开始的。但这里是猪国杀
14、for循环后i会+1,如重新从左到右看牌,i不能取1,要取0。
15、当牌堆没有牌时,会一直摸最后一张牌。(这就是RE点的原因吧)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 5 using namespace std; 6 7 const int N=15,M=2005; 8 9 int n,m,win,top,fan,usesha,liangshengfen; 10 11 char ch,pai; 12 13 bool vis[N][M],allsf[N]; 14 15 struct PIG{ 16 int liv,rit,tot,iden,leifan,biao,zhuge,xie; 17 int wuxie,sha,shan,tao; 18 char card[M+4]; 19 int used[M+4]; 20 }pig[N]; 21 22 char Card[M],sf[10]; 23 24 inline char readch() 25 { 26 ch=getchar(); 27 while(ch<'A'||ch>'Z') 28 ch=getchar(); 29 return ch; 30 } 31 32 inline void init() 33 { 34 scanf("%d%d",&n,&m); 35 for(int i=1;i<=n;++i) 36 { 37 pig[i].liv=1;pig[i].xie=4; 38 scanf("%s",sf); 39 switch(sf[0]) 40 { 41 case 'M':pig[i].iden=3;pig[i].biao=1;break; 42 case 'Z':pig[i].iden=1;break; 43 default: 44 fan++; 45 } 46 for(int j=1;j<=4;++j) 47 { 48 pai=readch(); 49 switch(pai) 50 { 51 case 'J': 52 pig[i].wuxie++;break; 53 case 'K': 54 pig[i].sha++;break; 55 case 'D': 56 pig[i].shan++;break; 57 case 'P': 58 pig[i].tao++;break; 59 60 } 61 pig[i].tot++; 62 pig[i].card[++pig[i].rit]=pai; 63 } 64 65 } 66 for(int i=1;i<=m;++i) 67 Card[i]=readch(); 68 top=1; 69 } 70 71 inline void yongtao(int u) 72 { 73 for(int i=1;i<=pig[u].rit;++i) 74 if(!pig[u].used[i]&&pig[u].card[i]=='P') 75 { 76 pig[u].used[i]=1; 77 return; 78 } 79 } 80 81 inline void yonggewuxie(int u) 82 { 83 for(int i=1;i<=pig[u].rit;++i) 84 if(!pig[u].used[i]&&pig[u].card[i]=='J') 85 { 86 pig[u].used[i]=1; 87 return; 88 } 89 } 90 91 inline void yongsha(int u,int ge) 92 { 93 if(!ge) 94 return; 95 for(int i=1;i<=pig[u].rit;++i) 96 if(!pig[u].used[i]&&pig[u].card[i]=='K') 97 { 98 pig[u].used[i]=1; 99 ge--; 100 if(!ge) 101 return; 102 } 103 } 104 105 inline void yongshan(int u) 106 { 107 for(int i=1;i<=pig[u].rit;++i) 108 if(!pig[u].used[i]&&pig[u].card[i]=='D') 109 { 110 pig[u].used[i]=1; 111 return; 112 } 113 } 114 115 int yongwuxie(int u,int good,int sta)//表身份 116 { 117 if(pig[u].biao==0) 118 { 119 if(pig[u].leifan==1) 120 { 121 if(good) return 0; 122 if(pig[1].wuxie) 123 { 124 pig[1].wuxie--; 125 pig[1].tot--; 126 yonggewuxie(1); 127 if(!yongwuxie(1,0,1)) return 1; 128 else return 0; 129 } 130 } 131 else 132 return 0; 133 } 134 int k=n,now=sta-1; 135 if(good) 136 { 137 while(k--) 138 { 139 now++; 140 if(now>n) 141 now=1; 142 if(!pig[now].liv) continue; 143 if((pig[now].iden&1)==(pig[u].iden&1)&&pig[now].wuxie) 144 { 145 pig[now].wuxie--; 146 pig[now].tot--; 147 yonggewuxie(now); 148 if(pig[now].biao==0) 149 pig[now].biao=1,liangshengfen=1; 150 if(!yongwuxie(now,0,now)) return 1; 151 else return 0; 152 } 153 } 154 return 0; 155 } 156 else 157 { 158 while(k--) 159 { 160 now++; 161 if(now>n) 162 now=1; 163 if(!pig[now].liv) continue; 164 if((pig[now].iden&1)!=(pig[u].iden&1)&&pig[now].wuxie) 165 { 166 pig[now].wuxie--; 167 pig[now].tot--; 168 yonggewuxie(now); 169 if(pig[now].biao==0) 170 pig[now].biao=1,liangshengfen=1; 171 if(!yongwuxie(now,0,now)) return 1; 172 else return 0; 173 } 174 } 175 return 0; 176 } 177 } 178 179 inline void mosanzhang(int u) 180 { 181 for(int j=1;j<=3;++j) 182 { 183 pai=Card[top++]; 184 if(top>m) top=m; 185 switch(pai) 186 { 187 case 'J': 188 pig[u].wuxie++;break; 189 case 'K': 190 pig[u].sha++;break; 191 case 'D': 192 pig[u].shan++;break; 193 case 'P': 194 pig[u].tao++;break; 195 } 196 pig[u].tot++; 197 pig[u].card[++pig[u].rit]=pai; 198 } 199 } 200 201 inline void diaoxie(int u,int now)//u使now掉血,处理死亡(不处理仇恨) 202 { 203 pig[now].xie--; 204 if(pig[now].xie==0) 205 { 206 if(pig[now].tao) 207 { 208 pig[now].xie=1; 209 pig[now].tot--; 210 pig[now].tao--; 211 yongtao(now); 212 } 213 else 214 { 215 pig[now].liv=0; 216 if(pig[now].iden==3) 217 { 218 win=2; 219 return; 220 } 221 if(pig[now].iden==1) 222 { 223 if(pig[u].iden==3) 224 { 225 pig[u].zhuge=0; 226 pig[u].tao=pig[u].sha=pig[u].shan=pig[u].wuxie=0; 227 for(int i=1;i<=pig[u].rit;++i) 228 pig[u].used[i]=0; 229 pig[u].rit=pig[u].tot=0; 230 return; 231 } 232 } 233 if(pig[now].iden==0) 234 { 235 fan--; 236 if(fan==0) 237 { 238 win=1; 239 return; 240 } 241 mosanzhang(u); 242 } 243 } 244 } 245 } 246 247 inline void nanman(int u)//无仇恨,只类反 248 { 249 int k=n-1,now=u; 250 while(k--) 251 { 252 now++; 253 if(now>n) now=1; 254 if(!pig[now].liv) continue; 255 if(!yongwuxie(now,1,u)) 256 { 257 if(pig[now].sha>0) 258 { 259 pig[now].sha--; 260 pig[now].tot--; 261 yongsha(now,1); 262 } 263 else 264 { 265 diaoxie(u,now); 266 if(pig[now].iden==3&&pig[u].biao==0) 267 pig[u].leifan=1; 268 } 269 } 270 if(win) return; 271 } 272 } 273 274 inline void wanjian(int u) 275 { 276 int k=n-1,now=u; 277 while(k--) 278 { 279 now++; 280 if(now>n) 281 now=1; 282 if(!pig[now].liv) continue; 283 if(!yongwuxie(now,1,u)) 284 { 285 if(pig[now].shan>0) 286 { 287 pig[now].shan--; 288 pig[now].tot--; 289 yongshan(now); 290 } 291 else 292 { 293 diaoxie(u,now); 294 if(pig[now].iden==3&&pig[u].biao==0) 295 pig[u].leifan=1; 296 } 297 } 298 if(win) return; 299 } 300 } 301 302 inline int doumubiao(int u) 303 { 304 if(!pig[u].iden) 305 return 1; 306 int now=u,k=n-1; 307 while(k--) 308 { 309 now++; 310 if(now>n) 311 now=1; 312 if(!pig[now].liv) 313 continue; 314 if(pig[now].biao==0) 315 { 316 if(u==1&&pig[now].leifan) 317 return now; 318 } 319 else 320 { 321 if((pig[now].iden&1)!=(pig[u].iden&1)) 322 return now; 323 } 324 } 325 return 0; 326 } 327 328 inline int juedou(int u,int now)//只计算掉血、杀 329 { 330 if(u==1&&pig[now].iden) 331 { 332 diaoxie(1,now); 333 return 0; 334 } 335 if(yongwuxie(now,1,u)) 336 return 0; 337 if(!pig[now].sha) 338 { 339 diaoxie(u,now); 340 return 0; 341 } 342 pig[now].sha--; 343 pig[now].tot--; 344 yongsha(now,1); 345 // if(yongwuxie(u,1)) 346 // return 0; 347 if(!pig[u].sha) 348 { 349 diaoxie(now,u); 350 return 1; 351 } 352 pig[u].sha--; 353 pig[u].tot--; 354 yongsha(u,1); 355 if(pig[now].sha>pig[u].sha) 356 { 357 pig[now].sha-=pig[u].sha+1; 358 pig[now].tot-=pig[u].sha+1; 359 yongsha(now,pig[u].sha+1); 360 yongsha(u,pig[u].sha); 361 pig[u].tot-=pig[u].sha; 362 pig[u].sha=0; 363 diaoxie(now,u); 364 return 1; 365 } 366 else 367 { 368 pig[u].sha-=pig[now].sha; 369 pig[u].tot-=pig[now].sha; 370 yongsha(u,pig[now].sha); 371 yongsha(now,pig[now].sha); 372 pig[now].tot-=pig[now].sha; 373 pig[now].sha=0; 374 diaoxie(u,now); 375 return 0; 376 } 377 } 378 379 inline void zhengli(int u) 380 { 381 int ccnt=0; 382 for(int i=1;i<=pig[u].rit;++i) 383 { 384 if(!pig[u].used[i]) 385 pig[u].card[++ccnt]=pig[u].card[i]; 386 else 387 pig[u].used[i]=0; 388 } 389 pig[u].rit=ccnt; 390 } 391 392 inline int nengyongsha(int u) 393 { 394 int k=n-1,now=u; 395 while(k--) 396 { 397 now++; 398 if(now>n) now=1; 399 if(!pig[now].liv) continue; 400 if(pig[u].iden==3) 401 { 402 if(pig[now].biao==1) 403 { 404 if(pig[now].iden==0) 405 return now; 406 else 407 return 0; 408 } 409 else 410 if(pig[now].leifan) 411 return now; 412 else 413 return 0; 414 } 415 if(pig[now].biao==0) 416 return 0; 417 if((pig[now].iden&1)!=(pig[u].iden&1)) 418 return now; 419 else 420 return 0; 421 } 422 return 0; 423 } 424 425 inline void chupai(int u) 426 { 427 int t; 428 int weiyongdou=0,weiyongsha=0,weiyongtao=0; 429 liangshengfen=0; 430 usesha=0; 431 for(int i=1;i<=pig[u].rit;++i) 432 if(!pig[u].used[i]) 433 { 434 switch(pig[u].card[i]) 435 { 436 case 'N': 437 pig[u].tot--; 438 pig[u].used[i]=1; 439 nanman(u); 440 break; 441 case 'F': 442 if(t=doumubiao(u)) 443 { 444 pig[u].used[i]=1; 445 pig[u].tot--; 446 pig[u].biao=1; 447 if(juedou(u,t))//自己掉血 448 { 449 if(weiyongtao>0) 450 { 451 yongtao(u); 452 pig[u].xie++; 453 pig[u].tao--; 454 pig[u].tot--; 455 weiyongtao--; 456 } 457 } 458 } 459 else 460 weiyongdou=1; 461 break; 462 case 'W': 463 pig[u].tot--; 464 pig[u].used[i]=1; 465 wanjian(u); 466 break; 467 case 'Z': 468 pig[u].zhuge=1; 469 pig[u].used[i]=1; 470 pig[u].tot--; 471 break; 472 case 'D':break; 473 case 'J':break; 474 case 'P': 475 if(pig[u].xie<4) 476 { 477 pig[u].xie++; 478 pig[u].tao--; 479 pig[u].used[i]=1; 480 } 481 else 482 weiyongtao++; 483 break; 484 case 'K': 485 if(!usesha||(pig[u].zhuge)) 486 { 487 if(t=nengyongsha(u)) 488 { 489 usesha=1; 490 pig[u].biao=1; 491 pig[u].used[i]=1; 492 pig[u].tot--; 493 pig[u].sha--; 494 if(pig[t].shan) 495 { 496 pig[t].shan--; 497 yongshan(t); 498 pig[t].tot--; 499 } 500 else 501 diaoxie(u,t); 502 } 503 else 504 weiyongsha=1; 505 } 506 else 507 weiyongsha=1; 508 break; 509 } 510 if(!pig[u].liv) 511 return; 512 if(win) return; 513 if(liangshengfen&&weiyongdou) 514 { 515 liangshengfen=0;weiyongdou=0; 516 i=0; 517 } 518 else 519 if(weiyongsha&&(!usesha||pig[u].zhuge)&&nengyongsha(u)) 520 { 521 weiyongsha=0; 522 i=0; 523 } 524 } 525 if(pig[u].rit>(pig[u].tot<<1)) 526 zhengli(u); 527 } 528 529 int main() 530 { 531 init(); 532 int now=1; 533 while(!win) 534 { 535 if(pig[now].liv) 536 { 537 for(int j=1;j<=2;++j) 538 { 539 pai=Card[top++]; 540 if(top>m) top=m; 541 switch(pai) 542 { 543 case 'J': 544 pig[now].wuxie++;break; 545 case 'K': 546 pig[now].sha++;break; 547 case 'D': 548 pig[now].shan++;break; 549 case 'P': 550 pig[now].tao++;break; 551 } 552 pig[now].tot++; 553 pig[now].card[++pig[now].rit]=pai; 554 } 555 chupai(now); 556 } 557 now++; 558 if(now>n) 559 now=1; 560 } 561 if(win==1) 562 printf("MP\n"); 563 else 564 printf("FP\n"); 565 for(int i=1;i<=n;++i) 566 { 567 if(!pig[i].liv) 568 printf("DEAD\n"); 569 else 570 { 571 for(int j=1;j<=pig[i].rit;++j) 572 if(!pig[i].used[j]) 573 { 574 printf("%c ",pig[i].card[j]); 575 } 576 putchar('\n'); 577 } 578 } 579 return 0; 580 }