[SDOI2010]猪国杀题解

题目链接:

洛谷P2482

loj2885

bzoj1972

推荐去loj看题,可以下数据因为特别容易出错

sol

其实这题码量也没那大,格式化后我的代码只有141行,在loj目前最短。最好多些一些函数,给每个猪开一个结构体。

游戏结束、一些数组/变量

之所以一开始就写结束,是因为以后要用。

void end() {
	puts(a[1].xue?"MP":"FP");//判断输赢
	for(int i=1; i<=n; i++) {//输出每只猪的状态
		if(a[i].xue==0)puts("DEAD");
		else {
			for(int j=0; j<a[i].s-1; j++)
				printf("%c ",a[i].pai[j]);
			if(a[i].s)printf("%c",a[i].pai[a[i].s-1]);
			puts("");
		}
	}
	exit(0);//退出整个程序
}

数组/变量

int nxt[15],las[15],top,f,n,m;
//nxt,las为链表,后会解释,top为牌堆顶,f为反猪数量,n为总猪数,m为总牌数
char tem[5],paidui[2010];//tem用来输入,paidui就是牌堆

每个猪的结构体:

struct pig {
	char tp,pai[2010];//tp:真实身份,M主猪,Z忠猪,F反猪,pai:手牌
	int xue,s,z,t;
	//xue:血量,s:牌数,z:是否有猪哥连弩(Z),t:表面身份,0:未知,1:忠猪,2:反猪,3:类反猪
	void qizhi(int &x) {//将第x张牌弃置
		s--;
		for(int i=x; i<s; i++)
			pai[i]=pai[i+1];
		x--;
	}
	int seach(char ch) {//搜索第一张为ch的牌,有就弃置,返回1,否则返回0
		for(int i=0; i<s; i++)
			if(pai[i]==ch) {
				qizhi(i);
				return 1;
			}
		return 0;
	}
	void mopai(int x) {//从牌堆中摸x张牌
		for(int i=1; i<=x; i++) {
			pai[s++]=paidui[top++];
			if(top==m)top--;
		}
	}
} a[15];

弃置我是暴力删,可以用vector<char>,然后摸牌有一个bug,牌不够用,要一直摸最后一张牌。

献殷勤、表敌意、跳忠、跳反

define两个语句

#define dipig(x,y) ((a[x].tp=='M'&&(a[y].t==2||a[y].t==3))||(a[x].tp=='Z'&&a[y].t==2)||(a[x].tp=='F'&&a[y].t==1))
\\x能否对y表敌意
#define youpig(x,y) (((a[x].tp=='M'||a[x].tp=='Z')&&a[y].t==1)||(a[x].tp=='F'&&a[y].t==2))
\\x能否对y献殷勤
\\y若未表明身份则都不能

跳忠、跳反很简单,如果他使用了『杀(K)』,『决斗(F)』,『无懈可击(J)』,就表明了身份,那么忠猪跳忠,反猪跳反。这里我把主猪当成一种特殊的忠猪,一开始就跳忠。

伤害、死亡

由于猪会死亡,且他们坐成一圈,所以我用了链表。

int nxt[15],las[15];//双向链表
void killed(int g,int p) {//g杀死了p
	if(a[p].tp=='M')end();//主猪死了,结束
	if(a[p].tp=='F') {
		if(!--f)end();//没有反猪了,结束
		a[g].mopai(3);//摸三张奖励牌
	} else if(a[p].tp=='Z'&&a[g].tp=='M')a[g].s=a[g].z=0;
	//主猪杀了忠猪,弃置所以牌和装备
	nxt[las[p]]=nxt[p];//从链表从删除p
	las[nxt[p]]=las[p];
}
void kouxue(int x,int y) {//以x为伤害来源,攻击y
	a[y].xue--;
	if(!a[y].xue)a[y].xue+=a[y].seach('P');//濒死,可以吃一个桃
	if(!a[y].xue)killed(x,y);//依然濒死,则y死亡
}

无懈可击

这是一个特殊的牌,可能可以递归使用。

int wxkj(int s,int x) {//无懈可击成功返回1,否则返回0
	for(int i=s,f=0; !f||i!=s; i=nxt[i],f=1) {//从s开始
		if((!x?(dipig(i,s)):(youpig(i,x)))&&a[i].seach('J')) {
		//如果x不为0,说明s对x使用锦囊牌,否则说明s是上一次使用无懈可击
		//根据题意判断是否使用无懈可击
			a[i].t=a[i].tp=='F'?2:1;//i的身份明确
			return !wxkj(i,0);//递归使用无懈可击
		}
	}
	return 0;
}

主要操作

终于到主要操作了~

	int now=1;//now为当前回合的猪
	a[1].t=1;//主猪一开始就跳忠
	if(!f)end();//一开始就没反猪
	while(1) {
		int kill=0;//是否使用过杀
		a[now].mopai(2);//摸2张牌
		for(int i=0; i<a[now].s&&a[now].xue; i++) {//枚举每张牌
			if(a[now].pai[i]=='Z') {//装备一定装备上,不管原来是否装备
				a[now].z=1,a[now].qizhi(i);
				i=-1;//可能之前杀可用,要从头枚举
			} else if(a[now].pai[i]=='P'&&a[now].xue<4) {//有桃一定吃
				a[now].xue++,a[now].qizhi(i);
			} else if(a[now].pai[i]=='K'&&(a[now].z||!kill)) {//能用杀
				int nx=nxt[now];//只能打下一个
				if(dipig(now,nx)) {//能表敌意
					a[now].t=a[now].tp=='F'?2:1;//now身份明确
					a[now].qizhi(i);
					kill=1;
					if(!a[nx].seach('D'))kouxue(now,nx);//nx没闪就扣血
				}
			} else if(a[now].pai[i]=='F') {//有决斗一定用
				for(int j=a[now].tp=='F'?1:nxt[now]; j!=now; j=nxt[j])
				//反猪一定与主猪决斗
					if(dipig(now,j)) {
						a[now].qizhi(i);
						a[now].t=a[now].tp=='F'?2:1;//now身份明确
						if(wxkj(now,j))break;//使用无懈可击
						if(a[j].tp=='Z'&&a[now].tp=='M') {
							kouxue(now,j);//主猪与忠猪决斗忠猪直接扣血
							break;
						}
						int t=1;
						while(1) {//决斗
							if(t==1) {
								if(!a[j].seach('K')) {
									kouxue(now,j);
									break;
								}
							} else if(!a[now].seach('K')) {
								kouxue(j,now),i=max(-1,i-1);
								break;
							}
							t^=1;
						}
						i=-1;
						//决斗可能会导致一些猪使用无懈可击,明确身份,要从头开始枚举牌
						break;
					}
			} else if(a[now].pai[i]=='N'||a[now].pai[i]=='W') {
				//有南猪入侵和万箭齐发一定用
				char ch=a[now].pai[i];//保存是哪种
				a[now].qizhi(i);
				for(int j=nxt[now]; j!=now; j=nxt[j]) {//依次结算
					if(!wxkj(now,j)&&!a[j].seach(ch=='N'?'K':'D')) {
						if(a[j].tp=='M'&&!a[now].t)a[now].t=3;
						//j是主猪,now未表明身份,则now为类反猪
						kouxue(now,j);
					}
				}
				i=-1;//同决斗,要从头开始枚举牌
			}
		}
		now=nxt[now];
	}

完整代码

注释就不打了

AC代码

#include<bits/stdc++.h>
using namespace std;
#define dipig(x,y) ((a[x].tp=='M'&&(a[y].t==2||a[y].t==3))||(a[x].tp=='Z'&&a[y].t==2)||(a[x].tp=='F'&&a[y].t==1))
#define youpig(x,y) (((a[x].tp=='M'||a[x].tp=='Z')&&a[y].t==1)||(a[x].tp=='F'&&a[y].t==2))
int nxt[15],las[15],top,f,n,m;
char tem[5],paidui[2010];
struct pig {
	char tp,pai[2010];
	int xue,s,z,t;
	void qizhi(int &x) {
		s--;
		for(int i=x; i<s; i++)
			pai[i]=pai[i+1];
		x--;
	}
	int seach(char ch) {
		for(int i=0; i<s; i++)
			if(pai[i]==ch) {
				qizhi(i);
				return 1;
			}
		return 0;
	}
	void mopai(int x) {
		for(int i=1; i<=x; i++) {
			pai[s++]=paidui[top++];
			if(top==m)top--;
		}
	}
} a[15];
void end() {
	puts(a[1].xue?"MP":"FP");
	for(int i=1; i<=n; i++) {
		if(a[i].xue==0)puts("DEAD");
		else {
			for(int j=0; j<a[i].s-1; j++)
				printf("%c ",a[i].pai[j]);
			if(a[i].s)printf("%c",a[i].pai[a[i].s-1]);
			puts("");
		}
	}
	exit(0);
}
void killed(int g,int p) {
	if(a[p].tp=='M')end();
	if(a[p].tp=='F') {
		if(!--f)end();
		a[g].mopai(3);
	} else if(a[p].tp=='Z'&&a[g].tp=='M')a[g].s=a[g].z=0;
	nxt[las[p]]=nxt[p];
	las[nxt[p]]=las[p];
}
void kouxue(int x,int y) {
	a[y].xue--;
	if(!a[y].xue)a[y].xue+=a[y].seach('P');
	if(!a[y].xue)killed(x,y);
}
int wxkj(int s,int x) {
	for(int i=s,f=0; !f||i!=s; i=nxt[i],f=1) {
		if((!x?(dipig(i,s)):(youpig(i,x)))&&a[i].seach('J')) {
			a[i].t=a[i].tp=='F'?2:1;
			return !wxkj(i,0);
		}
	}
	return 0;
}
int main() {
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; i++) {
		scanf("%s",tem);
		a[i].tp=tem[0];
		f+=tem[0]=='F';
		for(int j=0; j<4; j++)
			cin>>a[i].pai[j];
		nxt[i]=i+1,las[i]=i-1;
		a[i].s=a[i].xue=4;
	}
	for(int i=0; i<m; i++)cin>>paidui[i];
	nxt[n]=1,las[1]=n;
	int now=1;
	a[1].t=1;
	if(!f)end();
	while(1) {
		int kill=0;
		a[now].mopai(2);
		for(int i=0; i<a[now].s&&a[now].xue; i++) {
			if(a[now].pai[i]=='Z') {
				a[now].z=1,a[now].qizhi(i);
				i=-1;
			} else if(a[now].pai[i]=='P'&&a[now].xue<4) {
				a[now].xue++,a[now].qizhi(i);
			} else if(a[now].pai[i]=='K'&&(a[now].z||!kill)) {
				int nx=nxt[now];
				if(dipig(now,nx)) {
					a[now].t=a[now].tp=='F'?2:1;
					a[now].qizhi(i);
					kill=1;
					if(!a[nx].seach('D'))kouxue(now,nx);
				}
			} else if(a[now].pai[i]=='F') {
				for(int j=a[now].tp=='F'?1:nxt[now]; j!=now; j=nxt[j])
					if(dipig(now,j)) {
						a[now].qizhi(i);
						a[now].t=a[now].tp=='F'?2:1;
						if(wxkj(now,j))break;
						if(a[j].tp=='Z'&&a[now].tp=='M') {
							kouxue(now,j);
							break;
						}
						int t=1;
						while(1) {
							if(t==1) {
								if(!a[j].seach('K')) {
									kouxue(now,j);
									break;
								}
							} else if(!a[now].seach('K')) {
								kouxue(j,now),i=max(-1,i-1);
								break;
							}
							t^=1;
						}
						i=-1;
						break;
					}
			} else if(a[now].pai[i]=='N'||a[now].pai[i]=='W') {
				char ch=a[now].pai[i];
				a[now].qizhi(i);
				for(int j=nxt[now]; j!=now; j=nxt[j]) {
					if(!wxkj(now,j)&&!a[j].seach(ch=='N'?'K':'D')) {
						if(a[j].tp=='M'&&!a[now].t)a[now].t=3;
						kouxue(now,j);
					}
				}
				i=-1;
			}
		}
		now=nxt[now];
	}
	return 0;
}

观战模式

这个代码输出了每一步,每回合,有一个getchar

#include<bits/stdc++.h>
using namespace std;
#define dipig(x,y) ((a[x].tp=='M'&&(a[y].t==2||a[y].t==3))||(a[x].tp=='Z'&&a[y].t==2)||(a[x].tp=='F'&&a[y].t==1))
#define youpig(x,y) (((a[x].tp=='M'||a[x].tp=='Z')&&a[y].t==1)||(a[x].tp=='F'&&a[y].t==2))
int nxt[15],las[15],top,f,n,m;
char tem[5],paidui[2010];
struct pig {
	char tp,pai[2010];
	int xue,s,z,t;
	void qizhi(int &x) {
		s--;
		for(int i=x; i<s; i++)
			pai[i]=pai[i+1];
		x--;
	}
	int seach(char ch) {
		for(int i=0; i<s; i++)
			if(pai[i]==ch) {
				qizhi(i);
				return 1;
			}
		return 0;
	}
	void mopai(int x) {
		for(int i=1; i<=x; i++) {
			pai[s++]=paidui[top++];
			if(top==m)top--;
		}
	}
} a[15];
void end() {
	puts(a[1].xue?"MP":"FP");
	for(int i=1; i<=n; i++) {
		if(a[i].xue==0)puts("DEAD");
		else {
			for(int j=0; j<a[i].s-1; j++)
				printf("%c ",a[i].pai[j]);
			if(a[i].s)printf("%c",a[i].pai[a[i].s-1]);
			puts("");
		}
	}
	exit(0);
}
void killed(int g,int p) {
	if(a[p].tp=='M')end();
	if(a[p].tp=='F') {
		if(!--f)end();
		a[g].mopai(3);
	} else if(a[p].tp=='Z'&&a[g].tp=='M')a[g].s=a[g].z=0;
	nxt[las[p]]=nxt[p];
	las[nxt[p]]=las[p];
}
void kouxue(int x,int y) {
	a[y].xue--;
	if(!a[y].xue)
		if(a[y].seach('P'))a[y].xue++,cerr<<'P'<<' '<<y<<endl;
	if(!a[y].xue)killed(x,y);
}
int wxkj(int s,int x) {
	for(int i=s,f=0; !f||i!=s; i=nxt[i],f=1) {
		if((!x?(dipig(i,s)):(youpig(i,x)))&&a[i].seach('J')) {
			a[i].t=a[i].tp=='F'?2:1;
			cerr<<'J'<<' '<<i<<endl;
			return !wxkj(i,0);
		}
	}
	return 0;
}
int main() {
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; i++) {
		scanf("%s",tem);
		a[i].tp=tem[0];
		f+=tem[0]=='F';
		for(int j=0; j<4; j++)
			cin>>a[i].pai[j];
		nxt[i]=i+1,las[i]=i-1;
		a[i].s=a[i].xue=4;
	}
	for(int i=0; i<m; i++)cin>>paidui[i];
	nxt[n]=1,las[1]=n;
	int now=1;
	a[1].t=1;
	if(!f)end();
	while(1) {
		int kill=0;
		a[now].mopai(2);
		getchar();
		cerr<<now<<' '<<a[now].xue<<' '<<a[now].t<<' '<<a[now].z<<endl;
		for(int i=0; i<a[now].s; i++)cerr<<a[now].pai[i]<<' ';
		cerr<<endl;
		for(int i=0; i<a[now].s&&a[now].xue; i++) {
			if(a[now].pai[i]=='Z') {
				cerr<<'Z'<<endl;
				a[now].z=1,a[now].qizhi(i);
				i=-1;
			} else if(a[now].pai[i]=='P'&&a[now].xue<4) {
				cerr<<'P'<<endl;
				a[now].xue++,a[now].qizhi(i);
			} else if(a[now].pai[i]=='K'&&(a[now].z||!kill)) {
				int nx=nxt[now];
				if(dipig(now,nx)) {
					cerr<<'K'<<' '<<nx<<endl;
					a[now].t=a[now].tp=='F'?2:1;
					a[now].qizhi(i);
					kill=1;
					if(!a[nx].seach('D'))kouxue(now,nx);
					else cerr<<'D'<<endl;
				}
			} else if(a[now].pai[i]=='F') {
				for(int j=a[now].tp=='F'?1:nxt[now]; j!=now; j=nxt[j])
					if(dipig(now,j)) {
						cerr<<'F'<<' '<<j<<endl;
						a[now].qizhi(i);
						a[now].t=a[now].tp=='F'?2:1;
						if(wxkj(now,j))break;
						if(a[j].tp=='Z'&&a[now].tp=='M') {
							kouxue(now,j);
							break;
						}
						int t=1;
						while(1) {
							if(t==1) {
								if(!a[j].seach('K')) {
									kouxue(now,j);
									break;
								} else cerr<<'K'<<endl;
							} else if(!a[now].seach('K')) {
								kouxue(j,now),i=max(-1,i-1);
								break;
							} else cerr<<'K'<<endl;
							t^=1;
						}
						i=-1;
						break;
					}
			} else if(a[now].pai[i]=='N'||a[now].pai[i]=='W') {
				char ch=a[now].pai[i];
				a[now].qizhi(i);
				cerr<<ch<<endl;
				for(int j=nxt[now]; j!=now; j=nxt[j]) {
					if(wxkj(now,j))continue;
					if(!a[j].seach(ch=='N'?'K':'D')) {
						if(a[j].tp=='M'&&!a[now].t)a[now].t=3;
						kouxue(now,j);
					} else cerr<<(ch=='N'?'K':'D')<<endl;
				}
				i=-1;
			}
		}
		now=nxt[now];
	}
	return 0;
}
posted @ 2019-09-16 10:41  胡昊天  阅读(465)  评论(0编辑  收藏  举报