Luogu2482 [SDOI2010]猪国杀
题意
......
https://www.luogu.org/problemnew/show/P2482
总结
首先说一下代码的构思:
首先确定了所有的状态表示(例如游戏中游戏结束,不管有没有用),然后确定了所有属性什么的。
然后构思结构体的表达,并且从全局代码考虑需不需要这样设计(因为这个重构了一次,一开始写的结构体内的表示方法代码量大)
然后在结构体内写函数
然后提前分配好一些会用的全局变量,保存状态
然后先把程序入口输入输出写了
然后按照回合分函数,有一个回合分配函数,有一个出牌函数,每张牌都分了主动和被动两种出牌方式,每个函数都带有返回值(后面删掉了一些)
例如无懈可击的发起方有一个Cal_J函数然后去寻找目标,然后在Pas_J中处理猪的关系
例如给扣血的猪“办手续”,从扣血到死亡判定等等
在这中间打好注释,写好调试函数(例如在我的头文件模板中有Debug多参数函数)同时打好assert防止一些不必要的小地方出错(可以用Debug宏)
然后写一些细节函数,例如献殷勤表敌意
然后就是调节代码顺序,调试代码
一些经验吧......
- 提前分配好一些比较好的变量名
- 建议先声明函数再定义函数
- 打开Dev-C++的代码结构或者自己在草稿纸上写结构
- 每次调试之前自己浏览一遍代码并手推一遍样例,特别是修改了之后注意自己修改的地方,不要编译了历史版本
- 不要写的十分复杂,能简单写简单写
- 善用assert
- 善用注释
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //Created By Creeper_LKF 2 //Caution::We used "pragma" in the code 3 #include <cstdio> 4 #include <cctype> 5 #include <cassert> 6 #include <cstdlib> 7 #include <cstring> 8 #include <iostream> 9 10 #ifdef __gnu_linux__ 11 12 #include <fcntl.h> 13 #include <unistd.h> 14 #include <sys/mman.h> 15 16 #endif 17 18 #if __cplusplus < 201103L 19 20 #include <stdarg.h> 21 22 #endif 23 24 //Algorithm Heads 25 26 #include <list> 27 #include <queue> 28 #include <vector> 29 30 using namespace std; 31 32 //FILE_NAME DEFINATION 33 34 const char file_name[] = "b"; 35 36 #define NAME_SPACE 37 #define USING 38 39 #ifdef NAME_SPACE 40 namespace LKF{ 41 #endif 42 #define SF_READ 43 #define EOF_READ 44 // #define NEED_FILE 45 // #define WRITE_ENDL 46 // #define FAST_WRITE 47 const size_t MAX_BUF_SIZE = 50000000; 48 49 #ifdef FAST_WRITE 50 char outp[MAX_BUF_SIZE], *op = outp; 51 #endif 52 53 #ifdef DONLINE_JUDGE 54 #undef NEED_FILE 55 #endif 56 57 #ifdef FAST_WRITE 58 #ifndef WRITE_ENDL 59 #define WRITE_ENDL 60 #endif 61 #endif 62 63 extern inline void FILE_OPT(){ 64 #ifdef NEED_FILE 65 #define FILE_NAME file_name 66 char IN_FILE[sizeof(FILE_NAME) + 5], OUT_FILE[sizeof(FILE_NAME) + 5]; 67 strcpy(IN_FILE, FILE_NAME), strcpy(OUT_FILE, FILE_NAME); 68 strcat(IN_FILE, ".in"), strcat(OUT_FILE, ".out"); 69 freopen(IN_FILE, "r", stdin); 70 freopen(OUT_FILE, "w", stdout); 71 #endif 72 } 73 74 #ifdef __gnu_linux__ 75 76 char *pc; 77 78 extern inline void Main_Init(){ 79 static bool INITED = false; 80 if(INITED){ 81 #ifdef FAST_WRITE 82 fwrite(outp, 1, op - outp - 1, stdout); 83 #endif 84 fclose(stdin), fclose(stdout); 85 } else { 86 FILE_OPT(); 87 pc = (char *) mmap(NULL, lseek(0, 0, SEEK_END), PROT_READ, MAP_PRIVATE, 0, 0); 88 INITED = true; 89 } 90 } 91 92 #else 93 94 char buf[MAX_BUF_SIZE], *pc = buf; 95 96 extern inline void Main_Init(){ 97 static bool INITED = false; 98 if(INITED){ 99 #ifdef FAST_WRITE 100 fwrite(outp, 1, op - outp - 1, stdout); 101 #endif 102 fclose(stdin), fclose(stdout); 103 } else { 104 FILE_OPT(); 105 fread(buf, 1, MAX_BUF_SIZE, stdin); 106 INITED = true; 107 } 108 } 109 110 #endif 111 112 #ifdef EOF_READ 113 114 #ifdef SF_READ 115 116 template<typename T> 117 static inline void read(T &num){ 118 num = 0; 119 char c, sf = 1; 120 while(isspace(c = *pc++)); 121 if(c == 45) sf = -1, c = *pc ++; 122 while(num = num * 10 + c - 48, isdigit(c = *pc++)); 123 num *= sf; 124 } 125 126 static inline int read(){ 127 int num = 0; 128 char c, sf = 1; 129 while(isspace(c = *pc++)); 130 if(c == 45) sf = -1, c = *pc ++; 131 while(num = num * 10 + c - 48, isdigit(c = *pc++)); 132 return num * sf; 133 } 134 135 #else 136 137 template<typename T> 138 static inline T read(T &num){ 139 num = 0; 140 char c; 141 while (isspace(c = *pc++)); 142 while (num = num * 10 + c - 48, isdigit(c = *pc++)); 143 return num; 144 } 145 146 static inline int read(){ 147 int num = 0; 148 char c; 149 while (isspace(c = *pc++)); 150 while (num = num * 10 + c - 48, isdigit(c = *pc++)); 151 return num; 152 } 153 154 #endif 155 156 #else 157 158 #ifdef SF_READ 159 160 template<typename T> 161 static inline void read(T &num){ 162 num = 0; 163 char c, sf = 1; 164 while((c = *pc++) < 45); 165 if(c == 45) sf = -1, c = *pc ++; 166 while(num = num * 10 + c - 48, (c = *pc++) >= 48); 167 num *= sf; 168 } 169 170 static inline int read(){ 171 int num = 0; 172 char c, sf = 1; 173 while((c = *pc++) < 45); 174 if(c == 45) sf = -1, c = *pc ++; 175 while(num = num * 10 + c - 48, (c = *pc++) >= 48); 176 return num * sf; 177 } 178 179 #else 180 181 template<typename T> 182 static inline T read(T &num){ 183 num = 0; 184 char c; 185 while ((c = *pc++) < 48); 186 while (num = num * 10 + c - 48, (c = *pc++) >= 48); 187 return num; 188 } 189 190 static inline int read(){ 191 int num = 0; 192 char c; 193 while ((c = *pc++) < 48); 194 while (num = num * 10 + c - 48, (c = *pc++) >= 48); 195 return num; 196 } 197 198 #endif 199 200 #endif 201 202 #ifdef FAST_WRITE 203 template <typename T> 204 inline void Call_Write(char Split, T tar){ 205 char buf[20]; 206 int top = 0; 207 if(tar == 0) *op ++ = 48; 208 else { 209 if(tar < 0) *op ++ = '-'; 210 while(tar) buf[++top] = tar % 10, tar /= 10; 211 while(top) *op ++ = buf[top --] ^ 48; 212 } 213 *op ++ = Split; 214 } 215 template <typename T> 216 inline void Call_Write(T tar){ 217 char buf[20]; 218 int top = 0; 219 if(tar == 0) *op ++ = 48; 220 else { 221 if(tar < 0) *op ++ = '-'; 222 while(tar) buf[++top] = tar % 10, tar /= 10; 223 while(top) *op ++ = buf[top --] ^ 48; 224 } 225 } 226 #endif 227 228 #ifdef FAST_WRITE 229 230 extern inline void write(){ 231 *op ++ = '\n'; 232 } 233 234 template<typename T> 235 extern inline void write(T tar){ 236 Call_Write(tar); 237 #ifdef WRITE_ENDL 238 write(); 239 #endif 240 } 241 242 #if __cplusplus >= 201103L 243 244 # pragma GCC diagnostic push 245 # pragma GCC diagnostic ignored "-Wunused-parameter" 246 247 template<typename T> 248 extern inline void write(char Split, T tar){ 249 Call_Write(tar); 250 #ifdef WRITE_ENDL 251 write(); 252 #endif 253 } 254 255 # pragma GCC diagnostic pop 256 # pragma message "Warning : pragma used" 257 258 template<typename Head, typename T, typename... Tail> 259 extern inline void write(char Split, Head head, T mid, Tail... tail){ 260 Call_Write(Split, head); 261 write(Split, mid, tail...); 262 } 263 264 #else 265 266 template <typename T> 267 extern inline void write(char Split, T tar){ 268 Call_Write(tar); 269 #ifdef WRITE_ENDL 270 write(); 271 #endif 272 } 273 274 #endif 275 276 #else 277 278 extern inline void write(){ 279 cout << endl; 280 } 281 282 template<typename T> 283 extern inline void write(T tar){ 284 cout << tar; 285 #ifdef WRITE_ENDL 286 write(); 287 #endif 288 } 289 290 #if __cplusplus >= 201103L 291 292 template<typename T> 293 extern inline void write(char Split, T tar){ 294 cout << tar << Split; 295 } 296 297 template<typename Head, typename T, typename... Tail> 298 extern inline void write(char Split, Head head, T mid, Tail... tail){ 299 cout << head; 300 write(Split, mid, tail...); 301 } 302 303 #else 304 305 template <typename T> 306 extern inline void write(char Split, T tar){ 307 cout << tar << Split; 308 #ifdef WRITE_ENDL 309 write(); 310 #endif 311 } 312 313 #endif 314 315 #endif 316 317 template <typename T> 318 extern inline void upmax(T &x, const T &y){ 319 if(x < y) x = y; 320 } 321 template <typename T> 322 extern inline void upmin(T &x, const T &y){ 323 if(x > y) x = y; 324 } 325 326 #if __cplusplus >= 201103L 327 328 template<typename T> 329 extern inline T max(T tar){ 330 return tar; 331 } 332 333 template<typename T> 334 extern inline T min(T tar){ 335 return tar; 336 } 337 338 template <typename Head, typename T, typename... Tail> 339 extern inline Head max(Head head, T mid, Tail... tail){ 340 Head tmp = max(mid, tail...); 341 return head > tmp ? head : tmp; 342 } 343 template <typename Head, typename T, typename... Tail> 344 extern inline Head min(Head head, T mid, Tail... tail){ 345 Head tmp = min(mid, tail...); 346 return head < tmp ? head : tmp; 347 } 348 349 #else 350 351 template <typename T> 352 extern inline T max(T a, T b){ 353 return a > b ? a : b; 354 } 355 template <typename T> 356 extern inline T min(T a, T b){ 357 return a < b ? a : b; 358 } 359 360 #endif 361 362 template <typename T> 363 extern inline T abs(T tar){ 364 return tar < 0 ? -tar : tar; 365 } 366 template <typename T> 367 extern inline void swap(T &a, T &b){ 368 int t = a; 369 a = b; 370 b = t; 371 } 372 #ifdef NAME_SPACE 373 } 374 #endif 375 376 //Algorithm 377 378 #ifdef NAME_SPACE 379 namespace LKF{ 380 #endif 381 382 template <typename T> 383 struct Queue{ 384 size_t s, t; 385 T *q; 386 Queue(){ 387 s = 1, t = 0; 388 q = NULL; 389 } 390 Queue(size_t siz){ 391 q = (T*)malloc(sizeof(T) * siz); 392 assert(q != NULL); 393 } 394 ~Queue(){ 395 delete[] q; 396 } 397 inline void clear(){ 398 s = 1, t = 0; 399 } 400 inline bool empty(){ 401 return s > t; 402 } 403 inline size_t size(){ 404 return t - s + 1; 405 } 406 inline void push(T tar){ 407 q[++t] = tar; 408 } 409 inline void pop_front(){ 410 s++; 411 } 412 inline void pop_back(){ 413 t++; 414 } 415 inline T front(){ 416 return q[s]; 417 } 418 inline T back(){ 419 return q[t]; 420 } 421 }; 422 423 #ifdef NAME_SPACE 424 } 425 #endif 426 427 #ifdef USING 428 429 #ifdef NAME_SPACE 430 using LKF::read; 431 using LKF::Main_Init; 432 using LKF::write; 433 using LKF::upmax; 434 using LKF::upmin; 435 using LKF::max; 436 using LKF::min; 437 using LKF::abs; 438 // using LKF::swap; 439 #else 440 using ::read; 441 using ::Main_Init; 442 using ::write; 443 using ::upmax; 444 using ::upmin; 445 using ::max; 446 using ::min; 447 using ::abs; 448 // using ::swap; 449 #endif 450 451 #endif 452 453 //Source Code 454 455 using namespace std; 456 457 typedef list<int> CARD; 458 459 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Debug_Part~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 460 #if DEBUG 461 462 //Caution: Do Not Inline 463 //Do Not Open In Dev_CPP 464 465 void Print_Array(int s, int t, int *arr, string Name){ 466 cout << Name << " Begin" << endl; 467 for(int i = s; i < t; i++) cout << arr[i] << ' '; 468 cout << Name << " End" << endl; 469 } 470 471 void Print_List(CARD::iterator B, CARD::iterator E, string Name){ 472 cout << Name << " Begin" << endl; 473 for(CARD::iterator it = B; it != E; it++) 474 cout << *it << ' '; 475 cout << Name << " End" << endl; 476 } 477 478 479 #endif 480 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Read_Part~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 481 //This is SDOI2010 Killer of Pig Kingdom 482 //This is Release Version 483 484 inline char get_c(){ 485 char c; 486 while(!isalpha(c = *LKF::pc ++)); 487 return c; 488 } 489 490 //Caution:: 491 //Do not omit parentheses 492 493 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Const_Part~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 494 495 const int MAXN = 15, MAXM = 2018;//数组大小 496 const int GA = 0, MA = 1;//献殷勤,表敌意 497 const int ING = 0, MPG = 1, FPG = 2;//游戏状态 498 const int MP = 1, ZP = 2, AP = 3;//人物身份类型IDF,主猪,忠猪,反猪(同时表示主猪位置) 499 const int NN = 0, NS = 1, BZ = 2, BF = 3;//表示状态,未跳,类反猪,跳忠,跳反 500 const int P = 1, K = 2, D = 3;//基础类:桃,杀,闪 501 const int F = 4, N = 5, W = 6, J = 7;//技能类:决斗,南蛮入侵,万箭齐发,无懈可击 502 const int Z = 8;//装备类:诸葛连弩 503 const int FAIL = 0, SUCCEED = 1, GAME_OVER = 2; 504 505 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Variable_Part~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 506 507 int n, m, ReM, HP, FZ, Man_Now; 508 int Heap[MAXM]; 509 int Game_State; 510 511 struct Pig{ 512 int IDF, Health, IDS;//身份,血量,表态 513 int HC_CNT[MAXN], Dis[MAXN];//每种牌统计,距离 514 bool Death, ST_Z, ST_K;//死亡标记,诸葛连弩装备状态,出杀状态 515 CARD HC;//要求每次访问之前都有相应元素 516 Pig(){ 517 Death = false; 518 Health = 4; 519 IDF = 0; 520 HC.clear(); 521 } 522 inline void Add(int tar){//摸牌 523 HC.push_back(tar); 524 HC_CNT[tar]++; 525 } 526 inline int Get(){//出牌 527 int tar = HC.front(); 528 HC.pop_front(); 529 HC_CNT[tar]--; 530 return tar; 531 } 532 inline int Card(int Knd, int Num){//要求严格存在这些牌 533 CARD::iterator it; 534 int tim = 0; 535 for(it = HC.begin(); it != HC.end(); it++){ 536 if(*it == Knd){ 537 HC.erase(it); 538 HC_CNT[Knd]--; 539 tim++; 540 } 541 if(tim == Num) break; 542 } 543 #if DEBUG 544 assert(tim == Num); 545 #endif 546 return tim; 547 } 548 }pig[MAXN]; 549 550 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Mini_Function__Part~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 551 552 inline int CTI(char tar){ 553 switch(tar){ 554 case 'P' : return P; 555 case 'K' : return K; 556 case 'D' : return D; 557 case 'F' : return F; 558 case 'N' : return N; 559 case 'W' : return W; 560 case 'J' : return J; 561 case 'Z' : return Z; 562 } 563 return 0; 564 } 565 566 inline char ITC(int tar){ 567 static char ret[10] = {0, 'P', 'K', 'D', 'F', 'N', 'W', 'J', 'Z', 0}; 568 return ret[tar]; 569 } 570 571 inline int Deal_Card(){//不早说 572 if(HP == m) return Heap[m]; 573 return Heap[++HP]; 574 } 575 576 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Declaring_Part~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 577 578 inline void Input(); 579 580 inline void Solve(); 581 582 inline void Output(); 583 584 inline int New_Round(int); 585 586 inline void Reset_Dis(); 587 588 inline int Kill(int, int); 589 590 inline int DeaD(int, int); 591 592 inline int Dec_Health(int, int); 593 594 inline void Gallant(int, int); 595 596 inline void Malicious(int, int); 597 598 //被调用出牌 开始 599 600 inline int Pas_P(int); 601 inline int Pas_K(int, int); 602 inline int Pas_D(int); 603 inline int Pas_F(int, int); 604 inline int Pas_N(int); 605 inline int Pas_W(int); 606 inline int Pas_J(int, int, int); 607 inline int Pas_Z(int); 608 609 //被调用出牌 结束 610 611 //主动出牌 开始 612 613 inline int Cal_P(int); 614 inline int Cal_K(int); 615 inline int Cal_D(int, int); 616 inline int Cal_F(int); 617 inline int Cal_N(int); 618 inline int Cal_W(int); 619 inline int Cal_J(int, int, int); 620 inline int Cal_Z(int); 621 622 //主动出牌 结束 623 624 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Main_Part~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 625 626 int main(){ 627 Main_Init(); 628 Input(); 629 Solve(); 630 Output(); 631 return 0; 632 } 633 634 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Function_Part~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 635 636 inline void Input(){ 637 ReM = n = read(), m = read(); 638 for(int i = 1; i <= n; i++){ 639 char idf = get_c(); 640 switch(idf){ 641 case 'M' : pig[i].IDF = MP; break; 642 case 'Z' : pig[i].IDF = ZP; break; 643 case 'F' : pig[i].IDF = AP, FZ++; break; 644 } 645 get_c(); 646 for(int j = 1; j <= 4; j++) pig[i].Add(CTI(get_c())); 647 } 648 for(int i = 1; i <= m; i++) Heap[i] = CTI(get_c()); 649 } 650 651 inline void Solve(){ 652 if(FZ == 0){ 653 Game_State = MPG; 654 return ; 655 } 656 Reset_Dis(); 657 while(Game_State == ING){ 658 Man_Now++; 659 if(Man_Now == n + 1) Man_Now = 1; 660 if(pig[Man_Now].Death) continue; 661 New_Round(Man_Now); 662 } 663 } 664 665 inline void Output(){ 666 write('\n', Game_State == MPG ? "MP" : "FP"); 667 for(int i = 1; i <= n; i++){ 668 if(pig[i].Death) write('\n', "DEAD"); 669 else { 670 CARD::iterator it; 671 for(it = pig[i].HC.begin(); it != pig[i].HC.end(); it++){ 672 write(' ', ITC(*it)); 673 } 674 write(); 675 } 676 } 677 } 678 679 inline int New_Round(int Man){//注意:每次都会重新刷新序列(从头开始) 680 pig[Man].Add(Deal_Card()), pig[Man].Add(Deal_Card()); 681 pig[Man].ST_K = false; 682 CARD::iterator it; 683 int ret = 0, tar = 0; 684 // Print_List(pig[3].HC.begin(), pig[3].HC.end(), "3"); 685 for(it = pig[Man].HC.begin(); !pig[Man].Death && Game_State == ING && it != pig[Man].HC.end(); ){ 686 tar = *it, ret = 0; 687 switch(tar){ 688 case P : ret = Cal_P(Man); break; 689 case K : if(!pig[Man].ST_K || pig[Man].ST_Z) ret = bool(Cal_K(Man)), pig[Man].ST_K = ret; break; 690 // case D : ret = Cal_D(Man); break; 691 case F : ret = Cal_F(Man); break; 692 case N : ret = Cal_N(Man), ret = 1; break; 693 case W : ret = Cal_W(Man), ret = 1; break; 694 // case J : ret = Cal_J(Man); break; 695 case Z : ret = Cal_Z(Man), ret = 1; break; 696 }//要求在各函数内完成牌数统计 697 if(ret == FAIL) it++; 698 else it = pig[Man].HC.begin(); 699 } 700 return SUCCEED; 701 } 702 703 inline void Reset_Dis(){ 704 for(int i = 1; i <= n; i++){ 705 if(pig[i].Death) continue; 706 pig[i].Dis[i] = 0; 707 for(int j = i - 1, dis_now = ReM; j >= 1; j--){ 708 if(pig[j].Death) pig[i].Dis[j] = 0; 709 else pig[i].Dis[j] = --dis_now; 710 } 711 for(int j = i + 1, dis_now = 0; j <= n; j++){ 712 if(pig[j].Death) pig[i].Dis[j] = 0; 713 else pig[i].Dis[j] = ++dis_now; 714 } 715 } 716 } 717 718 inline int Dead(int dst, int scr){//返回0表示未死亡,返回1表示死亡,返回2表示游戏结束 719 if(pig[dst].HC_CNT[P] == 0) return bool(Kill(dst, scr)) + 1; 720 Pas_P(dst); 721 return FAIL; 722 } 723 724 inline int Kill(int dst, int scr){//返回0表示游戏继续,返回1表示MP胜利(状态MPG),返回2表示AP胜利(状态FPG) 725 pig[dst].Death = true; 726 pig[dst].ST_Z = false; 727 pig[dst].HC.clear(); 728 for(int i = 1; i < 10; i++) pig[dst].HC_CNT[i] = 0; 729 ReM--; 730 if(pig[dst].IDF == MP) return Game_State = FPG; 731 if(pig[dst].IDF == AP){ 732 FZ --; 733 if(!FZ) return Game_State = MPG; 734 pig[scr].Add(Deal_Card()), pig[scr].Add(Deal_Card()), pig[scr].Add(Deal_Card()); 735 } 736 if(pig[dst].IDF == ZP && pig[scr].IDF == MP){ 737 pig[scr].ST_Z = false; 738 pig[scr].HC.clear(); 739 for(int i = 1; i < 10; i++) pig[scr].HC_CNT[i] = 0; 740 } 741 Reset_Dis(); 742 return Game_State = ING; 743 } 744 745 inline int Dec_Health(int dst, int scr){//返回0表示未死亡,返回1表示已死亡,返回2表示游戏结束 746 pig[dst].Health --; 747 if(pig[dst].Health == 0) return Dead(dst, scr); 748 return FAIL; 749 } 750 751 inline void Malicious(int dst, int scr){ 752 if(pig[scr].IDF == MP) return ; 753 #if DEBUG 754 if(pig[dst].IDF == MP || pig[dst].IDS == BZ){ 755 assert(pig[scr].IDF != ZP); 756 pig[scr].IDS = BF; 757 } else if(pig[dst].IDS == BF){ 758 assert(pig[scr].IDF != AP); 759 pig[scr].IDS = BZ; 760 } 761 #endif 762 #if !DEBUG 763 if(pig[dst].IDF == MP || pig[dst].IDS == BZ) pig[scr].IDS = BF; 764 else if(pig[dst].IDS == BF) pig[scr].IDS = BZ; 765 #endif 766 } 767 768 inline void Gallant(int dst, int scr){ 769 if(pig[scr].IDF == MP) return ; 770 #if DEBUG 771 if(pig[dst].IDF == MP || pig[dst].IDS == BZ){ 772 assert(pig[scr].IDF != AP); 773 pig[scr].IDS = BZ; 774 } else if(pig[dst].IDS == BF){ 775 assert(pig[scr].IDF != ZP); 776 pig[scr].IDS = BF; 777 } 778 #endif 779 #if !DEBUG 780 if(pig[dst].IDF == MP || pig[dst].IDS == BZ) pig[scr].IDS = BZ; 781 else if(pig[dst].IDS == BF) pig[scr].IDS = BF; 782 #endif 783 } 784 785 inline int Cal_P(int Man){ 786 if(Pas_P(Man)) return SUCCEED; 787 return FAIL; 788 } 789 790 inline int Pas_P(int Man){//要求每次只加1血 791 if(pig[Man].Health == 4 || pig[Man].HC_CNT[P] == 0) return FAIL; 792 pig[Man].Card(P, 1); 793 pig[Man].Health ++; 794 return SUCCEED; 795 } 796 797 inline int Cal_K(int Man){//主动杀部分 798 if(pig[Man].IDF == MP){ 799 for(int i = 1; i < n; i++){ 800 int j = Man + i; 801 if(j > n) j = j - n; 802 if(pig[j].Death || pig[Man].Dis[j] > 1) continue; 803 if(pig[j].IDS == BF || pig[j].IDS == NS){ 804 Pas_K(j, Man); 805 return Cal_D(j, Man) == GAME_OVER ? GAME_OVER : SUCCEED; 806 } 807 } 808 return FAIL; 809 } 810 if(pig[Man].IDF == ZP){ 811 for(int i = 1; i < n; i++){ 812 int j = Man + i; 813 if(j > n) j = j - n; 814 if(pig[j].Death || pig[Man].Dis[j] > 1) continue; 815 if(pig[j].IDS == BF){ 816 Pas_K(j, Man); 817 return Cal_D(j, Man) == GAME_OVER ? GAME_OVER : SUCCEED; 818 } 819 } 820 return FAIL; 821 } 822 if(pig[Man].IDF == AP){ 823 if(pig[Man].Dis[MP] <= 1){ 824 Pas_K(MP, Man); 825 return Cal_D(MP, Man) == GAME_OVER ? GAME_OVER : SUCCEED; 826 } 827 for(int i = 1; i < n; i++){ 828 int j = Man + i; 829 if(j > n) j = j - n; 830 if(pig[j].Death || pig[Man].Dis[j] > 1) continue; 831 if(pig[j].IDF == MP || pig[j].IDS == BZ){ 832 Pas_K(j, Man); 833 return Cal_D(j, Man) == GAME_OVER ? GAME_OVER : SUCCEED; 834 } 835 } 836 return FAIL; 837 } 838 return FAIL; 839 } 840 841 inline int Pas_K(int dst, int scr){//允许对id=0的猪判断身份 842 if(dst) Malicious(dst, scr); 843 if(pig[scr].HC_CNT[K] == 0) return FAIL; 844 pig[scr].Card(K, 1); 845 return SUCCEED; 846 } 847 848 inline int Cal_D(int dst, int scr){ 849 if(Pas_D(dst) == FAIL) return Dec_Health(dst, scr); 850 return FAIL; 851 } 852 853 inline int Pas_D(int dst){//注意要求dst的方向与K不同 854 if(pig[dst].HC_CNT[D] == 0) return FAIL; 855 pig[dst].Card(D, 1); 856 return SUCCEED; 857 } 858 859 inline int Cal_F(int Man){//返回是否成功出牌 860 if(pig[Man].IDF == MP){ 861 for(int i = 1; i < n; i++){ 862 int j = Man + i; 863 if(j > n) j = j - n; 864 if(pig[j].Death) continue; 865 if(pig[j].IDS == BF || pig[j].IDS == NS){ 866 return Pas_F(j, Man), SUCCEED; 867 } 868 } 869 return FAIL; 870 } 871 if(pig[Man].IDF == ZP){ 872 for(int i = 1; i < n; i++){ 873 int j = Man + i; 874 if(j > n) j = j - n; 875 if(pig[j].Death) continue; 876 if(pig[j].IDS == BF){ 877 return Pas_F(j, Man), SUCCEED; 878 } 879 } 880 return FAIL; 881 } 882 if(pig[Man].IDF == AP){//直接表主猪 883 return Pas_F(MP, Man), SUCCEED; 884 /*for(int i = 1; i < n; i++){ 885 int j = Man + i; 886 if(j > n) j = j - n; 887 if(pig[j].Death) continue; 888 if(pig[j].IDF == MP || pig[j].IDS == BZ){ 889 return Pas_F(j, Man); 890 } 891 } 892 return FAIL;*/ 893 } 894 return FAIL; 895 } 896 897 inline int Pas_F(int dst, int scr){//返回scr出杀的数量 898 Malicious(dst, scr); 899 pig[scr].Card(F, 1); 900 if(Cal_J(dst, scr, GA)) return FAIL; 901 #if DEBUG 902 assert(!(pig[dst].IDF == MP && pig[scr].IDF == ZP)); 903 #endif 904 if(pig[dst].IDF == ZP && pig[scr].IDF == MP) return Dec_Health(dst, scr), 0;//主猪与忠猪的故事 905 int ret = 0; 906 while(true){ 907 if(Pas_K(0, dst) == FAIL) return Dec_Health(dst, scr), ret; 908 if(Pas_K(0, scr) == FAIL) return Dec_Health(scr, dst), ret;//WTF??? 909 ret++; 910 } 911 } 912 913 inline int Cal_J(int dst, int scr, int State){//使用无懈可击的发起方(枚举)是对接收方献殷勤还是表敌意,scr用于枚举起点 914 if(State == GA){//献殷勤,要求同边。注意逻辑不同,这里是枚举发起方,发起方知道自己的身份 915 if(pig[dst].IDF == MP){ 916 for(int i = 0; i < n; i++){ 917 int j = scr + i; 918 if(j > n) j = j - n; 919 if(pig[j].Death) continue; 920 if(pig[j].IDF == MP || pig[j].IDF == ZP){ 921 if(Pas_J(dst, j, GA)) return Cal_J(j, j, MA) ? FAIL : SUCCEED; 922 } 923 } 924 return FAIL; 925 } else if(pig[dst].IDS == BZ){ 926 for(int i = 0; i < n; i++){ 927 int j = scr + i; 928 if(j > n) j = j - n; 929 if(pig[j].Death) continue; 930 if(pig[j].IDF == ZP || pig[j].IDF == MP){ 931 if(Pas_J(dst, j, GA)) return Cal_J(j, j, MA) ? FAIL : SUCCEED; 932 } 933 } 934 return FAIL; 935 } else if(pig[dst].IDS == BF){ 936 for(int i = 0; i < n; i++){ 937 int j = scr + i; 938 if(j > n) j = j - n; 939 if(pig[j].Death) continue; 940 if(pig[j].IDF == AP){ 941 if(Pas_J(dst, j, GA)) return Cal_J(j, j, MA) ? FAIL : SUCCEED; 942 } 943 } 944 return FAIL; 945 } 946 } else { 947 if(pig[dst].IDF == MP){ 948 for(int i = 0; i < n; i++){ 949 int j = scr + i; 950 if(j > n) j = j - n; 951 if(pig[j].Death) continue; 952 if(pig[j].IDF == AP){ 953 if(Pas_J(dst, j, MA)) return Cal_J(j, j, MA) ? FAIL : SUCCEED; 954 } 955 } 956 return FAIL; 957 } else if(pig[dst].IDS == BZ){ 958 for(int i = 0; i < n; i++){ 959 int j = scr + i; 960 if(j > n) j = j - n; 961 if(pig[j].Death) continue; 962 if(pig[j].IDF == AP){ 963 if(Pas_J(dst, j, MA)) return Cal_J(j, j, MA) ? FAIL : SUCCEED; 964 } 965 } 966 return FAIL; 967 } else if(pig[dst].IDS == BF){ 968 for(int i = 0; i < n; i++){ 969 int j = scr + i; 970 if(j > n) j = j - n; 971 if(pig[j].Death) continue; 972 if(pig[j].IDF == MP || pig[j].IDF == ZP){ 973 if(Pas_J(dst, j, MA)) return Cal_J(j, j, MA) ? FAIL : SUCCEED; 974 } 975 } 976 return FAIL; 977 } else if(pig[dst].IDS == NS){//主猪对类反猪表敌意 978 if(Pas_J(dst, MP, MA)) return Cal_J(MP, MP, MA) ? FAIL : SUCCEED; 979 return FAIL; 980 } 981 } 982 return FAIL; 983 } 984 985 inline int Pas_J(int dst, int scr, int State){ 986 if(pig[scr].HC_CNT[J] == 0) return FAIL; 987 if(State == GA) Gallant(dst, scr); 988 else Malicious(dst, scr); 989 pig[scr].Card(J, 1); 990 return SUCCEED; 991 } 992 993 inline int Cal_N(int Man){ 994 assert(Pas_N(Man)); 995 for(int i = 1; i < n; i++){ 996 int j = Man + i; 997 if(j > n) j = j - n; 998 if(pig[j].Death) continue; 999 if(Cal_J(j, Man, GA) == SUCCEED) continue; 1000 if(Pas_K(0, j) == FAIL){ 1001 if(Dec_Health(j, Man) == GAME_OVER) return GAME_OVER; 1002 if(j == MP && pig[Man].IDS == NN) pig[Man].IDS = NS; 1003 } 1004 } 1005 return SUCCEED; 1006 } 1007 1008 inline int Pas_N(int dst){ 1009 if(pig[dst].HC_CNT[N] == 0) return FAIL; 1010 pig[dst].Card(N, 1); 1011 return SUCCEED; 1012 } 1013 1014 inline int Cal_W(int Man){ 1015 assert(Pas_W(Man)); 1016 for(int i = 1; i < n; i++){ 1017 int j = Man + i; 1018 if(j > n) j = j - n; 1019 if(pig[j].Death) continue; 1020 if(Cal_J(j, Man, GA) == SUCCEED) continue; 1021 if(Pas_D(j) == FAIL){ 1022 if(Dec_Health(j, Man) == GAME_OVER) return GAME_OVER; 1023 if(j == MP && pig[Man].IDS == NN) pig[Man].IDS = NS; 1024 } 1025 } 1026 return SUCCEED; 1027 } 1028 1029 inline int Pas_W(int dst){ 1030 if(pig[dst].HC_CNT[W] == 0) return FAIL; 1031 pig[dst].Card(W, 1); 1032 return SUCCEED; 1033 } 1034 1035 inline int Cal_Z(int Man){ 1036 return Pas_Z(Man); 1037 } 1038 1039 inline int Pas_Z(int dst){ 1040 if(pig[dst].HC_CNT[Z] == 0) return FAIL; 1041 pig[dst].ST_Z = true; 1042 pig[dst].Card(Z, 1); 1043 return SUCCEED; 1044 }