[SDOI2010] 猪国杀
NOIp前最后皮一下,祝自己RP++。
从昨天晚上开始写,一直写到现在才A......
在LXD大佬的帮助下,终于A掉了......
还发现有两道大模拟,一个是琪露诺的冰雪小屋,一个是杀蚂蚁,有兴趣的可以看一下。
先说这个猪国杀:
我写了几个指针只是为了简化代码QAQ。
这道题题意挺清楚的,我就说几个坑点。
一个是如果牌堆里没牌了,要一直拿最后一个。
还有就是,决斗的伤害来源是受到伤害的人的另一个人,决斗不会出现自己伤害自己的情况。
如果有人掉血要立即判断是否死亡。
如果有人死亡要立即判断游戏是否结束。
如果能结束要立即结束,不要有其它摸牌或出牌的操作。
用函数封装一些操作能有效缩减代码长度,方便调试及查错。
像我就只写了不到300行,5kb左右。感觉还是挺简洁的,何况还没怎么过分压行。
感觉代码可读性还是很强的,就没写注释。
特别需要注意无懈可击的写法,要寻找是否有人想出无懈。
如果有,还要继续递归地无懈下去。
最后还要有返回值判断这个无懈最终是否会有效果。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 int n,m; 8 9 int inv(int fr,int kd); 10 int findinv(int st,int kd); 11 void kill(int fr,int to); 12 void duel(int fr,int to); 13 void check(); 14 void end(int result); 15 16 struct SCARDS 17 { 18 char cds[2005];int tp; 19 char give() 20 { 21 if(tp==m)return cds[m]; 22 return cds[tp++]; 23 } 24 }cards; 25 26 struct SPIG 27 { 28 int hp,cnt,num;char card[2005],id[5]; 29 bool crossbow,antilike,anti,faith,dead; 30 SPIG *last,*nx; 31 void getcard(){card[++cnt]=cards.give();} 32 void getcard(char cd){card[++cnt]=cd;} 33 bool known(){return (anti||faith);} 34 bool has(char cd) 35 { 36 for(int i=1;i<=cnt;i++) 37 if(card[i]==cd)return 1; 38 return 0; 39 } 40 void use(char cd) 41 { 42 for(int i=1;i<=cnt;i++) 43 if(card[i]==cd){card[i]='x';return;} 44 } 45 void extort(char crd) 46 { 47 SPIG* pt=nx; 48 while(pt!=this) 49 { 50 int k=0; 51 if(pt->anti)k=findinv(num,0); 52 if(pt->faith)k=findinv(num,1); 53 if(k)k=inv(k,(pt->faith)); 54 if(!k) 55 { 56 if(pt->has(crd))pt->use(crd); 57 else 58 { 59 pt->hurt(num); 60 if(pt->id[1]=='M'&&(!known())) 61 antilike=1; 62 } 63 } 64 pt=pt->nx; 65 } 66 } 67 void play() 68 { 69 getcard();getcard(); 70 bool kl=0; 71 for(int i=1;i<=cnt&&(!dead);i++) 72 { 73 if(card[i]=='x'||card[i]=='D')continue; 74 if(card[i]=='Z')card[i]='x',crossbow=1,i=0; 75 if(card[i]=='P'&&hp<4)card[i]='x',hp++; 76 if(card[i]=='N')card[i]='x',extort('K'),i=0; 77 if(card[i]=='W')card[i]='x',extort('D'),i=0; 78 if(card[i]=='K'&&((!kl)||crossbow)) 79 { 80 if(id[1]=='M') 81 if(nx->antilike||nx->anti) 82 card[i]='x',kill(num,nx->num),kl=1,i=0; 83 if(id[1]=='Z') 84 if(nx->anti) 85 card[i]='x',kill(num,nx->num),kl=1,i=0; 86 if(id[1]=='F') 87 if((nx->faith)||(nx->id[1]=='M')) 88 card[i]='x',kill(num,nx->num),kl=1,i=0; 89 } 90 if(card[i]=='F') 91 { 92 if(id[1]=='M') 93 { 94 SPIG *pt=nx; 95 while(pt!=this) 96 { 97 if((pt->antilike)||(pt->anti)) 98 { 99 card[i]='x'; 100 duel(num,pt->num),i=0; 101 break; 102 } 103 pt=(pt->nx); 104 } 105 } 106 if(id[1]=='Z') 107 { 108 SPIG *pt=nx; 109 while(pt!=this) 110 { 111 if(pt->anti) 112 { 113 card[i]='x'; 114 duel(num,pt->num),i=0; 115 break; 116 } 117 pt=(pt->nx); 118 } 119 } 120 if(id[1]=='F')card[i]='x',duel(num,1),i=0; 121 } 122 } 123 } 124 bool save() 125 { 126 if(has('P'))return use('P'),hp++,1; 127 return 0; 128 } 129 void hurt(int cause); 130 }pig[15]; 131 132 void SPIG::hurt(int cause) 133 { 134 hp--; 135 if(hp)return; 136 if(save())return; 137 dead=1; 138 check(); 139 last->nx=nx;nx->last=last; 140 if(pig[cause].dead)return; 141 if(id[1]=='Z'&&pig[cause].id[1]=='M') 142 { 143 for(int i=1;i<=pig[cause].cnt;i++) 144 pig[cause].card[i]='x'; 145 pig[cause].crossbow=0; 146 } 147 if(id[1]=='F') 148 for(int i=1;i<=3;i++) 149 pig[cause].getcard(); 150 } 151 152 void kill(int fr,int to) 153 { 154 if(pig[to].has('D'))pig[to].use('D'); 155 else pig[to].hurt(fr); 156 if(pig[to].id[1]=='M'||pig[to].faith) 157 pig[fr].anti=1; 158 if(pig[to].anti) 159 pig[fr].faith=1,pig[fr].antilike=0; 160 } 161 162 void duel(int fr,int to) 163 { 164 if(pig[fr].id[1]=='M'&&pig[to].id[1]=='Z') 165 {pig[to].hurt(fr);return;} 166 int k=0; 167 if(pig[fr].id[1]!='M') 168 { 169 if(pig[to].anti)pig[fr].faith=1,pig[fr].antilike=0; 170 else pig[fr].anti=1; 171 } 172 if(pig[to].anti)k=findinv(fr,0); 173 if(pig[to].faith)k=findinv(fr,1); 174 if(k)k=inv(k,pig[to].faith); 175 if(!k) 176 { 177 int fir=to,sec=fr; 178 while(1) 179 { 180 if(pig[fir].has('K')) 181 pig[fir].use('K'),fir^=sec^=fir^=sec; 182 else 183 {pig[fir].hurt(sec);break;} 184 } 185 } 186 } 187 188 int inv(int fr,int kd) 189 { 190 pig[fr].use('J'); 191 if(kd)pig[fr].faith=1,pig[fr].antilike=0; 192 else pig[fr].anti=1; 193 int k=findinv(fr,1-kd); 194 if(k)return 1-inv(k,1-kd); 195 else return 1; 196 } 197 198 int findinv(int st,int kd) 199 { 200 SPIG* pt=&pig[st]; 201 do 202 { 203 if((!kd)&&pt->id[1]=='F'&&pt->has('J')) 204 return pt->num; 205 if(kd&&(pt->id[1]=='Z'||pt->id[1]=='M')&&pt->has('J')) 206 return pt->num; 207 pt=pt->nx; 208 }while(pt->num!=st); 209 return 0; 210 } 211 212 void check() 213 { 214 bool good=0,bad=0; 215 for(int i=1;i<=n;i++) 216 { 217 if(pig[i].id[1]=='M'&&pig[i].dead)end(0); 218 if(!pig[i].dead) 219 { 220 if(pig[i].id[1]=='F')bad=1; 221 else good=1; 222 } 223 if(good&&bad)return; 224 } 225 end(good); 226 } 227 228 void end(int result) 229 { 230 if(result)printf("MP\n"); 231 else printf("FP\n"); 232 for(int i=1;i<=n;i++) 233 { 234 if(pig[i].dead)printf("DEAD"); 235 else 236 for(int j=1;j<=pig[i].cnt;j++) 237 if(pig[i].card[j]!='x') 238 printf("%c ",pig[i].card[j]); 239 printf("\n"); 240 } 241 exit(0); 242 } 243 244 int main() 245 { 246 scanf("%d%d",&n,&m); 247 for(int i=1;i<=n;i++) 248 { 249 scanf("%s",pig[i].id+1); 250 for(int j=1;j<=4;j++) 251 { 252 char cd[5]; 253 scanf("%s",cd+1); 254 pig[i].getcard(cd[1]); 255 } 256 pig[i].hp=4;pig[i].num=i; 257 if(i==n)pig[i].nx=&pig[1]; 258 else pig[i].nx=&pig[i+1]; 259 if(i==1)pig[i].last=&pig[n]; 260 else pig[i].last=&pig[i-1]; 261 } 262 pig[1].faith=1;cards.tp=1; 263 for(int i=1;i<=m;i++) 264 { 265 char tmp[5]; 266 scanf("%s",tmp+1); 267 cards.cds[i]=tmp[1]; 268 } 269 check(); 270 while(true) 271 for(int i=1;i<=n;i++) 272 if(!pig[i].dead)pig[i].play(); 273 }