Description
Solution
这个题是真的不难写……唯一的难度就在于理解题意上面……感觉这就是个阅读理解题啊……
而且你三国杀玩的越多可能就越难写因为你无法理解那些猪的思维……
Asia:这些猪会强制把你变得和他们一样sb,然后用他们丰富的sb经验来打败你
细节就不说了……说几个我写挂或者遗漏的点吧:
1、手牌不要从左扫到右扫完一遍就结束了……可能后面发生了什么事件导致你前面的牌又可以用了。
2、无懈可击的写法:我是不停的递归下去直到一方没有无懈可击为止 不知道有没有别的写法
3、牌堆没牌的话就不停摸牌堆最后一张,直到结束为止。这里好像题目里没有说……?
4、决斗无限距离且反贼只会直接去决斗刚主公
一些具体细节可以看代码实现……太多了就不说了……
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<vector> 6 #include<queue> 7 #define N (15) 8 using namespace std; 9 10 struct Pig 11 { 12 int hp;//血量 13 int id;//真实身份 123主忠反 14 int id2;//跳明身份 01是否跳明 2类反 15 int bow;//是否装有武器 16 vector<char>card;//可打出的手牌 17 }p[N]; 18 queue<char>q;//牌堆 19 char opt[3],a[2],b[2],c[2],d[2]; 20 int n,m,Fnum,cpos; 21 22 void debug(int x) 23 { 24 cout<<x<<':'; 25 for (int i=0; i<p[x].card.size(); ++i) 26 printf("%c ",p[x].card[i]); 27 puts(""); 28 } 29 30 void Print() 31 { 32 for (int i=1; i<=n; ++i) 33 if (p[i].hp==0) puts("DEAD"); 34 else 35 { 36 for (int j=0; j<p[i].card.size(); ++j) 37 printf("%c ",p[i].card[j]); 38 puts(""); 39 } 40 exit(0); 41 } 42 43 int Dis(int x,int y)//计算距离 44 { 45 int ans=1; 46 for (int i=x%n+1; i!=y; i=i%n+1) 47 if (p[i].hp>0) ans++; 48 return ans; 49 } 50 51 void Solve(int from,int x,char opt,int cnt)//伤害来源,结算角色,需要的卡牌,需要的张数。 52 { 53 for (int i=0; i<p[x].card.size();) 54 if (p[x].card[i]!=opt || cnt==0) ++i; 55 else p[x].card.erase(p[x].card.begin()+i),cnt--; 56 if (cnt>0) 57 { 58 p[x].hp--; 59 if (p[x].id==1 && !p[from].id2) p[from].id2=2; 60 } 61 if (p[x].hp==0) 62 { 63 for (int i=0; i<p[x].card.size();) 64 if (p[x].card[i]!='P') ++i; 65 else 66 { 67 p[x].card.erase(p[x].card.begin()+i); 68 p[x].hp=1; break; 69 } 70 if (p[x].hp!=0) return; 71 cpos=0;//有人死亡后手牌重新从最左开始扫 72 if (p[x].id==3) Fnum--; 73 if (p[x].id==1) 74 puts("FP"),Print(); 75 if (!Fnum) 76 puts("MP"),Print(); 77 78 if (p[x].id==2 && p[from].id==1) 79 p[from].bow=0, p[from].card.clear(); 80 if (p[x].id==3) 81 { 82 for (int i=1; i<=3; ++i) 83 { 84 p[from].card.push_back(q.front()); 85 if (q.size()>1) q.pop(); 86 } 87 } 88 } 89 } 90 91 bool check(int x,int y,int opt)//检查x对y是否合法,opt为将要进行的类型 1献殷勤2表敌意 92 { 93 if (p[x].hp==0 || p[y].hp==0) return false; 94 int idx=p[x].id==3?2:1; 95 int idy=p[y].id==3?2:1; 96 if (idx!=idy && p[y].id2==1 && opt==2) return true; 97 if (idx==idy && p[y].id2==1 && opt==1) return true; 98 if (p[y].id2==2 && p[x].id==1 && opt==2) return true; 99 return false; 100 } 101 102 int WXKJ(int pos,int opt,int tar)//这一轮开始的位置,当前是否生效1生效2无效,目标 103 { 104 if (check(pos,tar,opt)) 105 for (int i=0; i<p[pos].card.size();++i) 106 if (p[pos].card[i]=='J') 107 { 108 if (p[pos].id2!=1) p[pos].id2=1,cpos=0; 109 p[pos].card.erase(p[pos].card.begin()+i); 110 return WXKJ(pos,opt==1?2:1,tar); 111 } 112 113 for (int i=pos%n+1; i!=pos; i=i%n+1) 114 if (check(i,tar,opt)) 115 for (int j=0; j<p[i].card.size();++j) 116 if (p[i].card[j]=='J') 117 { 118 if (p[i].id2!=1) p[i].id2=1,cpos=0; 119 p[i].card.erase(p[i].card.begin()+j); 120 return WXKJ(i,opt==1?2:1,tar); 121 } 122 return opt; 123 } 124 125 int main() 126 { 127 scanf("%d%d",&n,&m); 128 for (int i=1; i<=n; ++i) 129 { 130 scanf("%s%s%s%s%s",opt,a,b,c,d); 131 if (opt[0]=='M') p[i].id=1,p[i].id2=1; 132 if (opt[0]=='Z') p[i].id=2; 133 if (opt[0]=='F') p[i].id=3,Fnum++; 134 p[i].hp=4; 135 p[i].card.push_back(a[0]); p[i].card.push_back(b[0]); 136 p[i].card.push_back(c[0]); p[i].card.push_back(d[0]); 137 } 138 for (int i=1; i<=m; ++i) 139 scanf("%s",a),q.push(a[0]); 140 if (!Fnum){puts("MP");Print();return 0;} 141 142 int now=1; 143 while (1) 144 { 145 bool kill=false; 146 p[now].card.push_back(q.front()); 147 if (q.size()>1) q.pop(); 148 p[now].card.push_back(q.front()); 149 if (q.size()>1) q.pop(); 150 // debug(now); 151 for (cpos=0; cpos<p[now].card.size();) 152 { 153 if (p[now].hp==0) break; 154 switch (p[now].card[cpos]) 155 { 156 case 'P'://桃 157 { 158 if (p[now].hp<4) 159 { 160 p[now].hp++; 161 p[now].card.erase(p[now].card.begin()+cpos); 162 } 163 else ++cpos; 164 break; 165 } 166 case 'K'://杀 167 { 168 if (kill && !p[now].bow){++cpos; break;} 169 bool vis=false; 170 for (int i=now%n+1; i!=now; i=i%n+1) 171 if (check(now,i,2) && Dis(now,i)<=1) 172 { 173 vis=true; kill=true; 174 p[now].card.erase(p[now].card.begin()+cpos); 175 Solve(now,i,'D',1); 176 if (p[now].id2!=1) p[now].id2=1,cpos=0; 177 break; 178 } 179 if (!vis) ++cpos; 180 break; 181 } 182 case 'F'://决斗 183 { 184 bool vis=false; 185 int tar=-1; 186 if (p[now].id==3) tar=1; 187 else 188 for (int i=now%n+1; i!=now; i=i%n+1) 189 if (check(now,i,2)){tar=i; break;} 190 if (tar==-1){++cpos; break;} 191 192 p[now].card.erase(p[now].card.begin()+cpos); 193 if (p[now].id2!=1) p[now].id2=1,cpos=0; 194 if (WXKJ(now,1,tar)==2) break; 195 int cnt1=0,cnt2=0; 196 for (int k=0; k<p[now].card.size(); ++k) 197 if (p[now].card[k]=='K') cnt1++; 198 for (int k=0; k<p[tar].card.size(); ++k) 199 if (p[tar].card[k]=='K') cnt2++; 200 if (p[now].id==1 && p[tar].id==2) 201 Solve(now,tar,'?',1); 202 else 203 { 204 Solve(now,tar,'K',cnt1+1); 205 Solve(tar,now,'K',cnt2); 206 } 207 break; 208 } 209 case 'N'://南蛮入侵 210 { 211 p[now].card.erase(p[now].card.begin()+cpos); 212 for (int i=now%n+1; i!=now; i=i%n+1) 213 { 214 if (p[i].hp==0) continue; 215 if (WXKJ(now,1,i)==2) continue; 216 Solve(now,i,'K',1); 217 } 218 break; 219 } 220 case 'W'://万箭齐发 221 { 222 p[now].card.erase(p[now].card.begin()+cpos); 223 for (int i=now%n+1; i!=now; i=i%n+1) 224 { 225 if (p[i].hp==0) continue; 226 if (WXKJ(now,1,i)==2) continue; 227 Solve(now,i,'D',1); 228 } 229 break; 230 } 231 case 'Z'://诸葛连弩 232 { 233 p[now].bow=1; 234 p[now].card.erase(p[now].card.begin()+cpos); 235 cpos=0; break; 236 } 237 default: ++cpos; 238 } 239 } 240 now=now%n+1; 241 while (p[now].hp==0) now=now%n+1; 242 } 243 }