zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    站点被百度惩处应从哪些方面分析
    SVN 权限配置具体说明
    关于数组的应用
    实现键值对存储(二)——以现有键值对存储为模型
    大数据Lambda架构
    关于c++primer的一个代码错误
    怎样解决Ubuntu发热严重地问题
    【maven】pom.xml文件没错,但是项目有小红叉,Problems中可以看到错误:“Dynamic Web Module 3.0 requires Java 1.6 or newer.”
    【shiro】2.spring整合shiro,注解控制shiro用户/角色/权限And/OR,没有权限跳转到固定页面
    【shiro】使用shiro搭建的项目,页面引用js,报错:Uncaught SyntaxError: Unexpected token <
  • 原文地址:https://www.cnblogs.com/hht2005/p/11526075.html
Copyright © 2011-2022 走看看