P2482 [SDOI2010] 猪国杀
著名题目(
写+调大概一晚上+一上午
(可能)难以理解的题意:
- 主猪身份公开
- 南猪入侵、万箭齐发只转一圈(对每个人结算一次)
- 如果 A 无懈了 B 对 C 发起的南猪入侵、万箭齐发、决斗,那么 A 对 C 献殷勤
- 如果之后有 D 无懈了 A 的无懈可击,那么 D 对 A 表敌意;同样,后面每个人无懈上一个人的无懈可击时,都算且仅算作对上一个人表敌意
- 南猪入侵、万箭齐发结算到某个人时,先看是否有人使用无懈可击(并且成功,也就是没有被别的无懈无懈掉),再看是否能出杀或闪
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<assert.h>
#include<vector>
inline char getLetter(){
char c=getchar();
while(c<'A'||c>'Z') c=getchar();
return c;
}
#define N 12
#define M 2006
#define HP_LIM 4
struct Pig{
char type;
int look,hp,mulKill;//look: 0=none 1=类反猪 2=已跳忠 3=已跳反 4=已死
std::vector<char>card;
inline void init(){
type=getLetter();getLetter();
card.push_back(getLetter());card.push_back(getLetter());card.push_back(getLetter());card.push_back(getLetter());
hp=HP_LIM;look=0;mulKill=0;
}
};
int n,m,cntFP;
Pig p[N];
int nex[N];
char card[M];
int cardNow;
inline char getCard(){if(++cardNow>m) cardNow=m;return card[cardNow];}
inline void output(){
puts(cntFP?"FP":"MP");
for(int i=1;i<=n;i++){
if(p[i].look==4) puts("DEAD");
else{
for(std::vector<char>::iterator now=p[i].card.begin();now!=p[i].card.end();now++) printf("%c ",*now);
puts("");
}
}
}
inline void dead(int u,int v){//u killed v
p[v].hp--;p[v].look=4;p[v].mulKill=0;std::vector<char>().swap(p[v].card);
for(int i=1;i<=n;i++)if(nex[i]==v&&p[i].look!=4) nex[i]=nex[v];
if(p[v].type=='M') output(),exit(0);
else if(p[v].type=='F'){
if(!--cntFP) output(),exit(0);
p[u].card.push_back(getCard()),p[u].card.push_back(getCard()),p[u].card.push_back(getCard());
}
else if(p[v].type=='Z'&&p[u].type=='M') std::vector<char>().swap(p[u].card),p[u].mulKill=0;
}
inline void makeHostility(int u,int v){
if(p[v].type=='M'||p[v].look==2) p[u].look=3;
else if(p[v].look==3) p[u].look=2;
}
inline int canMakeHostility(int i,int j){
return (p[i].type=='M'&&(p[j].look==1||p[j].look==3))||(p[i].type=='Z'&&p[j].look==3)||(p[i].type=='F'&&(p[j].type=='M'||p[j].look==2));
}
inline void makeGoodwill(int u,int v){
if(p[v].type=='M'||p[v].look==2) p[u].look=2;
else if(p[v].look==3) p[u].look=3;
}
inline int canMakeGoodwill(int u,int v){
return ((p[u].type=='M'||p[u].type=='Z')&&(p[v].type=='M'||p[v].look==2))||(p[u].type=='F'&&p[v].look==3);
}
inline int use(int u,char c){
for(std::vector<char>::iterator now=p[u].card.begin();now!=p[u].card.end();now++)
if(*now==c) return p[u].card.erase(now),1;
return 0;
}
inline void attack(int u,int v){
if(p[v].hp<=1){
if(use(v,'P')) return;
dead(u,v);
}
else p[v].hp--;
}
inline int tryUseJ(int user,int target,int attitude){//尝试使用无懈可击使 user 使用的锦囊失效,attitude: 1=殷勤 2=敌意(对 target)
int u=user;
do{
if(((attitude==1&&canMakeGoodwill(u,target))||(attitude==2&&canMakeHostility(u,target)))&&use(u,'J')){
if(attitude==1) makeGoodwill(u,target);
else if(attitude==2) makeHostility(u,target);
return !tryUseJ(u,u,2);
}
u=nex[u];
}while(u!=user);
return 0;
}
inline void useKill(int u,int v){//u use kill to v
makeHostility(u,v);
if(use(v,'D')) return;
attack(u,v);
}
inline void useDuel(int u,int v){//u use duel to v
makeHostility(u,v);
if(tryUseJ(u,v,1)) return;
for(;;){
if((p[u].type=='M'&&p[v].type=='Z')||!use(v,'K')) return attack(u,v),void();
if((p[v].type=='M'&&p[u].type=='Z')||!use(u,'K')) return attack(v,u),void();
}
}
inline void makeRound(int id){
p[id].card.push_back(getCard());p[id].card.push_back(getCard());
int usedKill=0;
START_ROUND:
for(std::vector<char>::iterator now=p[id].card.begin();now!=p[id].card.end();now++){
if(*now=='P'){
if(p[id].hp==HP_LIM) continue;
p[id].hp++;p[id].card.erase(now);
goto START_ROUND;
}
else if(*now=='K'){
if(usedKill&&!p[id].mulKill) continue;
if(canMakeHostility(id,nex[id])){
p[id].card.erase(now);usedKill=1;useKill(id,nex[id]);
goto START_ROUND;
}
}
else if(*now=='Z'){
p[id].card.erase(now);p[id].mulKill=1;
goto START_ROUND;
}
else if(*now=='F'){
if(p[id].type=='F'){
for(int j=nex[id];j!=id;j=nex[j])if(p[j].type=='M'){
p[id].card.erase(now);useDuel(id,j);
goto START_ROUND;
}
}
for(int j=nex[id];j!=id;j=nex[j])if(canMakeHostility(id,j)){
p[id].card.erase(now);useDuel(id,j);
goto START_ROUND;
}
}
else if(*now=='N'){
p[id].card.erase(now);
for(int j=nex[id];j!=id;j=nex[j]){
if(tryUseJ(id,j,1)) continue;
if(use(j,'K')) continue;
attack(id,j);
if(p[j].type=='M'&&!p[id].look) p[id].look=1;
}
goto START_ROUND;
}
else if(*now=='W'){
p[id].card.erase(now);
for(int j=nex[id];j!=id;j=nex[j]){
if(tryUseJ(id,j,1)) continue;
if(use(j,'D')) continue;
attack(id,j);
if(p[j].type=='M'&&!p[id].look) p[id].look=1;
}
goto START_ROUND;
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) p[i].init();
for(int i=1;i<=m;i++) card[i]=getLetter();
for(int i=1;i<=n;i++) cntFP+=(p[i].type=='F');
for(int i=1;i<n;i++) nex[i]=i+1;nex[n]=1;
for(int i=1;;i=nex[i]) makeRound(i);
return 0;
}