suxxsfe

一言(ヒトコト)

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;
}
posted @ 2022-05-24 19:19  suxxsfe  阅读(97)  评论(0编辑  收藏  举报