P2482 [SDOI2010] 豬國殺
阿新 • • 發佈:2022-05-24
著名題目(
寫+調大概一晚上+一上午
(可能)難以理解的題意:
- 主豬身份公開
- 南豬入侵、萬箭齊發只轉一圈(對每個人結算一次)
- 如果 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; }