0%

SDOI2019-猪国杀

没什么好说的,就是写完了发个代码

获得修正:心情+10 ( -1每天 )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include <bits/stdc++.h>
#define rei register int
using namespace std;

const int N=15,M=2100;
const int MAX_HP=4;
const int INF=0x3f3f3f3f;
char ide_MP[N];//在主猪眼中的身份
char card_heap[M];//谔谔,这个堆第1个是最底下一张,也就是说存的时候是反着存的
int n,m,num_FP;
bool ended,used_kill;
//这个地方,将used_kill作为局部变量时,用int &修改报错惹
//又用了函数返回值维护但还是错了
//但放到外面就对了

char tmp[10];
struct pig{
int Next,Last,HP;
// bool isMP,isZP,isFP;//谔谔这样存猪的身份的话需要同时维护这三个和ide_MP中的身份
char ide;
bool crossbow;
int cardnum; char card[M];

inline void clear_card(){ cardnum=0; crossbow=false;}
inline void get_card(int num){//摸牌数量
for(rei i=1;i<=num;++i) card[++cardnum]=card_heap[ m==0 ? m=1 : m ],--m;
}
}pig[N];

namespace SETTLE{//settlement
inline void print(){//结算
puts(pig[1].HP ? "MP" : "FP");
for(rei i=1;i<=n;++i){
if(!pig[i].HP){ puts("DEAD"); continue;}
for(rei j=1;j<=pig[i].cardnum;++j) if(pig[i].card[j]!='U') printf("%c ",pig[i].card[j]);
puts("");
}
}
}

namespace COND{//condition
inline bool enable_to_kill(int a,int b){
if(used_kill && !pig[a].crossbow) return 0;
if(pig[a].ide=='M' && ide_MP[b]!='L' && ide_MP[b]!='F') return 0;
if(pig[a].ide=='Z' && ide_MP[b]!='F') return 0;
if(pig[a].ide=='F' && ide_MP[b]!='M' && ide_MP[b]!='Z') return 0;
return 1;
}
inline void if_killed(int a,int b){//a killed b?
for(rei i=1;i<=pig[b].cardnum;++i) if(pig[b].card[i]=='P') return pig[b].card[i]='U',++pig[b].HP,void();
pig[ pig[b].Next ].Last=pig[b].Last; pig[ pig[b].Last ].Next=pig[b].Next;//更改距离
if(pig[b].ide=='F'){
--num_FP;
if(!num_FP) return ended=1,void();
pig[a].get_card(3);//先判断是否胜利再摸牌
}
if(pig[b].ide=='M') return ended=1,void();
if(pig[b].ide=='Z' && pig[a].ide=='M') pig[a].clear_card();
}
inline void duel_with(int a,int &b){//a duel with b,get_b
if(pig[a].ide=='F') return b=1,void();
for(rei i=pig[a].Next;i!=a;i=pig[i].Next) if((pig[a].ide=='M' && (pig[i].ide=='L' || pig[i].ide=='F')) || (pig[a].ide=='Z' && pig[i].ide=='F')) return b=i,void();
}
}

namespace CARD{
inline bool unbreakable(int x1,int x2,int x3){
rei i=x1,pd=x3 ? x2 : x1;
while(1){
if(x3==1){
if(ide_MP[x2]==pig[i].ide || (ide_MP[x2]=='M' && pig[i].ide=='Z') || (ide_MP[x2]=='Z' && pig[i].ide=='M')){
for(rei j=1;j<=pig[i].cardnum;++j) if(pig[i].card[j]=='J'){
pig[i].card[j]='U'; ide_MP[i]=pig[i].ide;
return !unbreakable(i,x1,0);
}
}
}
else{
if(((pig[i].ide=='M' || pig[i].ide=='Z') && ide_MP[x1]=='F') || (pig[i].ide=='F' && (ide_MP[x1]=='M' || ide_MP[x1]=='Z')))
for(rei j=1;j<=pig[i].cardnum;++j) if(pig[i].card[j]=='J'){
pig[i].card[j]='U'; ide_MP[i]=pig[i].ide;
return !unbreakable(i,x1,0);
}
}
i=pig[i].Next;
if(i==x1) break;
}
return false;
}
inline void bas_usecard_P(int id,int x){ if(pig[id].HP<MAX_HP){ ++pig[id].HP; pig[id].card[x]='U';}}//used
inline void bas_usecard_K(int id,int x){//x为id猪的第x张牌
rei nnext=pig[id].Next;
if(!COND::enable_to_kill(id,nnext)) return ;
used_kill=1;
pig[id].card[x]='U';
for(rei i=1;i<=pig[nnext].cardnum;++i) if(pig[nnext].card[i]=='D') return pig[nnext].card[i]='U',void();
--pig[nnext].HP; if(!pig[nnext].HP) COND::if_killed(id,nnext);
ide_MP[id]=pig[id].ide;
}
inline void equip_crossbow(int id,int x){ pig[id].crossbow=true; pig[id].card[x]='U';}
inline void oper_duel(int a,int b){
// if(--无懈可击--) return ;
if(unbreakable(a,b,1)) return ;
if(a==1 && pig[b].ide=='Z'){
--pig[b].HP;
if(!pig[b].HP) COND::if_killed(a,b);
return ;
}
rei j=1,k=1;
while(1){
while(pig[b].card[j]!='K' && j<=pig[b].cardnum) ++j;
if(j>pig[b].cardnum){
--pig[b].HP;if(!pig[b].HP) COND::if_killed(a,b);
return ;
}
else pig[b].card[j]='U';
while(pig[a].card[k]!='K' && k<=pig[a].cardnum) ++k;
if(k>pig[a].cardnum){
--pig[a].HP; if(!pig[a].HP) COND::if_killed(b,a);
return ;
}
else pig[a].card[k]='U';
}
}
inline int spe_usecard_duel(int id,int x){//这里注意,当没有决斗目标时,j不需要归0,所以有返回值
if(pig[id].ide=='F'){
pig[id].card[x]='U',oper_duel(id,1);
ide_MP[id]=pig[id].ide;
return 1;
}
for(int k=pig[id].Next;k!=id;k=pig[k].Next)
if((pig[id].ide=='M' && (ide_MP[k]=='L' || ide_MP[k]=='F')) || (pig[id].ide=='Z' && ide_MP[k]=='F')){
pig[id].card[x]='U',oper_duel(id,k);
ide_MP[id]=pig[id].ide;
return 1;
}
return 0;
}
inline void spe_usecard_invade(int id,int x){
pig[id].card[x]='U';
for(rei i=pig[id].Next;i!=id;i=pig[i].Next){
// if(--无懈可击--) continue;
if(unbreakable(id,i,1)) continue;
rei i_now=1;
for(;i_now<=pig[i].cardnum;++i_now) if(pig[i].card[i_now]=='K'){ pig[i].card[i_now]='U'; break;}
if(i_now>pig[i].cardnum){
if(i==1 && ide_MP[id]=='U') ide_MP[id]='L';//注意这里的误伤
--pig[i].HP; if(!pig[i].HP) COND::if_killed(id,i);
if(ended) return ;
}
}
}
inline void spe_usecard_arrow(int id,int x){
pig[id].card[x]='U';
for(rei i=pig[id].Next;i!=id;i=pig[i].Next){
// if(--无懈可击--) continue;
if(unbreakable(id,i,1)) continue;
rei i_now=1;
for(;i_now<=pig[i].cardnum;++i_now) if(pig[i].card[i_now]=='D'){ pig[i].card[i_now]='U'; break;}
if(i_now>pig[i].cardnum){
if(i==1 && ide_MP[id]=='U') ide_MP[id]='L';//注意这里的误伤
--pig[i].HP; if(!pig[i].HP) COND::if_killed(id,i);
if(ended) return ;
}
}
}
}

inline void Begin(){
if(!num_FP) return ;
for(rei i=1;i;i=pig[i].Next){
used_kill=0;
pig[i].get_card(2);
for(rei j=1;j<=pig[i].cardnum;++j){//每次出牌都要判断是否已经胜利,而不是在换人的时候判断
if(!pig[i].HP) break;
char C=pig[i].card[j]; if(C=='U') continue;
if(C=='P') CARD::bas_usecard_P(i,j);
else if(C=='K'){ CARD::bas_usecard_K(i,j); if(ended) return ;}
else if(C=='Z') CARD::equip_crossbow(i,j),j=0;
else if(C=='F'){ CARD::spe_usecard_duel(i,j) ? j=0 : 0; if(ended) return ;}
else if(C=='N'){ CARD::spe_usecard_invade(i,j),j=0; if(ended) return ;}
else if(C=='W'){ CARD::spe_usecard_arrow(i,j),j=0; if(ended) return ;}
}
}
}

int main(){
// freopen("1.in","r",stdin); freopen("1.ans","w",stdout);
scanf("%d%d",&n,&m);
for(rei i=1;i<=n;++i) pig[i].Next=i+1,pig[i].Last=i-1;
pig[n].Next=1,pig[1].Last=n;
for(rei i=1;i<=n;++i){
for(rei j=1;j<M;++j) pig[i].card[j]='U';
scanf("%s",tmp); pig[i].ide=tmp[0];
for(rei j=1;j<=4;++j) scanf("%s",tmp),pig[i].card[j]=tmp[0];
pig[i].HP=pig[i].cardnum=4;
if(pig[i].ide=='F') ++num_FP;
}
ide_MP[1]='M'; for(rei i=2;i<=n;++i) ide_MP[i]='U';
for(rei i=1;i<=m;++i) scanf("%s",tmp),card_heap[m-i+1]=tmp[0];
Begin();
SETTLE::print();
getchar(),getchar();
return 0;
}