[SDOI2010]猪国杀 解题报告

这道题作为一道省选题,质量真是差到了极点!!强烈建议千万不要去做!


首先,这题意与数据不合,而样例怎么看都是错的,反猪明明有6张无懈!

题意与数据之龃龉:

①题目中n<=5,而实际上n<=10.

②题目中明确指出不会出现牌不够用的情况,而实际上你需要不断地抽最后一张牌。

也就是说,如果你按照题目要求写的话,你的最终得分将是:30分。。。(←_←这种题考场上能有人A才怪。)

而如果你RP爆发把数组开到10,那么你就能拿90分。。

我写的时候没有考虑到的地方:

①装诸葛连弩可能导致前面出杀。

②与他人决斗可能导致自己死亡,此时应及时中止出牌阶段!!←←←←此处最大坑点。

③反猪的决斗永远是献给主猪的(而不是什么逆时针第一个。。)。

④题目中的距离与平常意义上的距离不一样!是逆时针旋转的距离!


犯的一些SB错误:

①把>0写成>9.

②把pig[j].id<0写成j<0.

③企图用break退出switch的外层循环(实际上只能退switch,而如果是if的话这么做是可以退到循环的)。

代码(循题面拿30分):

#include
using namespace std;
#include
#include
#include
#include
#include
#include
#include
struct LS{
	int data;
	LS * pred,* succ; 
}pl[5000];
int tot;

struct PS{
	int blood,id;//-3:跳了的反;-2:没跳的反;-1:就是反的类反;0:死猪;1:其实是忠的类反;2:没跳的忠;3:跳了的忠;4:主公 
	bool zhuge;//判断是否装备诸葛 
	LS begin[9],end[9];
}pig[5];
int pred[5],next[5];//猪们的链表 
int heap[2000],m,n;//保存牌堆什么的。 
int fsum;//保存反猪的数量 
map revf;map f;//映射们 
bool flag;//是否有人又跳了。 

inline char gt(){//读取字符 
	char c=getchar();
	while(c<'A'||c>'Z')c=getchar();
	return c;
}
inline void got(int i,int pai){//猪i获得了牌pai
	pl[tot]=(LS){pai,pig[i].end[0].pred,pig[i].end};
	pig[i].end[0].pred->succ=pl+tot,pig[i].end[0].pred=pl+tot++;
	
	pl[tot]=(LS){pai,pig[i].end[pai].pred,pig[i].end+pai};
	pig[i].end[pai].pred->succ=pl+tot,pig[i].end[pai].pred=pl+tot++;
}
inline void del(int i){//弃置牌i 
	pl[i].pred->succ=pl[i].succ;
	pl[i].succ->pred=pl[i].pred;
	
	pl[i^1].pred->succ=pl[i^1].succ;
	pl[i^1].succ->pred=pl[i^1].pred;
}
inline void out(){//输出
	for(int i=0;isucc){
				putchar(revf[j->data]);
				if(j->succ!=pig[i].end)putchar(' ');
			}
		else printf("DEAD");
		putchar('\n');
	}
}
inline bool hate(int i,int j){//判断pig i是否讨厌pig j
	return pig[i].id==4&&abs(pig[j].id)==1||pig[i].id>0&&pig[j].id==-3||pig[i].id<0&&pig[j].id>=3;
}
inline void attack(int i,int j){//j受到来自i的一点伤害 
	if(--pig[j].blood==0){
		if(pig[j].begin[1].succ==pig[j].end+1){//判断j是否会死 
			//从链表中将其删除 
			next[pred[j]]=next[j];
			pred[next[j]]=pred[j];
			flag=1;
			//判断j的身份
			if(pig[j].id<0)--fsum;
			//判断游戏是否结束
			if(j*fsum==0){
				if(j)printf("MP");
				else printf("FP");
				
				putchar('\n');
				out();
				exit(0);
			}
			//判断是否存在奖励/惩罚
			if(pig[j].id>0&&i==0){
				pig[0].zhuge=0;
				for(int k=9;k--;){
					pig[0].begin[k].succ=pig[0].end+k;
					pig[0].end[k].pred=pig[0].begin+k;
				}
			}
			else if(pig[j].id<0)for(j=3;j--;)got(i,heap[--m]);
		}
		else{
			del(pig[j].begin[1].succ-pl);
			++pig[j].blood;
		}
	}
}
inline bool require(int i,int j,int p){//pig i向pig j请求一张p,否则pig i将向pig j造成1点伤害 
	if(pig[j].begin[p].succ==pig[j].end+p){
		attack(i,j);
		return 0;
	}
	else{
		del(pig[j].begin[p].succ-pl);
		return 1;
	}
} 
inline void update(int i){//i跳了 
	if(pig[i].id>0&&pig[i].id<3)pig[i].id=3,flag=1;
	else if(pig[i].id<0&&pig[i].id>-3)pig[i].id=-3,flag=1;
}
inline bool find(int i,int flag){//从i开始,寻找身份为flag的猪打出无懈可击;同时认为其献殷勤/表敌意,跳反/忠 
	if(abs(flag)<3)return 0;
	if(pig[i].id*flag>0&&pig[i].begin[7].succ!=pig[i].end+7){
		del(pig[i].begin[7].succ-pl);
		update(i);
		return !find(i,-flag);
	}
	for(int j=next[i];j!=i;j=next[j])
		if(pig[j].id*flag>0&&pig[j].begin[7].succ!=pig[j].end+7){
			del(pig[j].begin[7].succ-pl);
			update(j);
			return !find(j,-flag);
		} 
	return 0;
}
inline void req(int i,int p){//pig i向所有人请求p 
	int blood=pig[0].blood;
	for(int j=next[i];j!=i;j=next[j])
		if(!find(i,pig[j].id))
			require(i,j,p);
	if(pig[0].blood!=blood&&abs(pig[i].id)==2){
		flag=1;
		pig[i].id/=2;
	}
}
int main(){
	int i,j;
	scanf("%d%d",&n,&m);
	//预处理
		//映射 
	f['P']=1,	f['K']=2,	f['D']=3,	f['F']=4,	f['N']=5,	f['W']=6,	f['J']=7,	f['Z']=8;
	revf[1]='P',revf[2]='K',revf[3]='D',revf[4]='F',revf[5]='N',revf[6]='W',revf[7]='J',revf[8]='Z';
		//预处理单向链表,指向下一个还活着的猪。 
	for(i=n;--i;)next[i-1]=i,pred[i]=i-1;
	next[n-1]=0,pred[0]=n-1;
		//预处理猪们的牌表和血量。 
	for(i=n;i--;){
		pig[i].blood=4;
		for(j=9;j--;)pig[i].begin[j].succ=pig[i].end+j,pig[i].end[j].pred=pig[i].begin+j;
	}
	//Read
	for(i=0;isucc){
			switch(ptr->data){
				case 1:
					if(pig[i].blood<4){
						del(ptr-pl);
						++pig[i].blood;
					}
					break;
				case 2:
					if(notyet|pig[i].zhuge&&fuck1+1){
						update(i);
						del(ptr-pl);
						notyet=0;
						require(i,fuck1,3);
					}
					break;
				case 8:
					del(ptr-pl);
					if(pig[i].zhuge==0){
						pig[i].zhuge=1;
						flag=1;
					}
					break;
				case 4:
					if(fuck2!=i){
						del(ptr-pl);
						update(i);
						if(!find(i,pig[fuck2].id)){
							if(i==0&&pig[fuck2].id>0)attack(i,fuck2);
							else
								while(1){
									if(!require(i,fuck2,2))break;
									if(!require(fuck2,i,2))break;
								}
						}
					}
					break;
				case 5:
					del(ptr-pl);
					req(i,2);
					break;
				case 6:
					del(ptr-pl);
					req(i,3);
					break;
			}
			if(flag){
				flag=0;
				fuck1=hate(i,next[i])?next[i]:-1;
				if(pig[i].id<0)fuck2=0;
				else{
					fuck2=next[i];
					while(fuck2!=i&&!hate(i,fuck2))fuck2=next[fuck2];
				}
				ptr=pig[i].begin;
			}
		} 
	}
}

代码(AC):

#include
using namespace std;
#include
#include
#include
#include
#include
#include
#include
struct LS{
	int data;
	LS * pred,* succ; 
}pl[1000000];
int tot;

struct PS{
	int blood,id;//-3:跳了的反;-2:没跳的反;-1:就是反的类反;0:死猪;1:其实是忠的类反;2:没跳的忠;3:跳了的忠;4:主公 
	bool zhuge;//判断是否装备诸葛 
	LS begin[9],end[9];
}pig[50];
int pred[50],next[50];//猪们的链表 
int heap[10000],m,n;//保存牌堆什么的。 
int fsum;//保存反猪的数量 
map revf;map f;//映射们 
bool flag;//是否有人又跳了。 

inline char gt(){//读取字符 
	char c=getchar();
	while(c<'A'||c>'Z')c=getchar();
	return c;
}
inline void got(int i,int pai){//猪i获得了牌pai
	pl[tot]=(LS){pai,pig[i].end[0].pred,pig[i].end};
	pig[i].end[0].pred->succ=pl+tot,pig[i].end[0].pred=pl+tot++;
	
	pl[tot]=(LS){pai,pig[i].end[pai].pred,pig[i].end+pai};
	pig[i].end[pai].pred->succ=pl+tot,pig[i].end[pai].pred=pl+tot++;
}
inline void del(int i){//弃置牌i 
	pl[i].pred->succ=pl[i].succ;
	pl[i].succ->pred=pl[i].pred;
	
	pl[i^1].pred->succ=pl[i^1].succ;
	pl[i^1].succ->pred=pl[i^1].pred;
}
inline void out(){//输出
	for(int i=0;isucc){
				putchar(revf[j->data]);
				if(j->succ!=pig[i].end)putchar(' ');
			}
		else printf("DEAD");
		putchar('\n');
	}
}
inline bool hate(int i,int j){//判断pig i是否讨厌pig j
	return pig[i].id==4&&abs(pig[j].id)==1||pig[i].id>0&&pig[j].id==-3||pig[i].id<0&&pig[j].id>=3;
}
inline void attack(int i,int j){//j受到来自i的一点伤害 
	if(--pig[j].blood==0){
		if(pig[j].begin[1].succ==pig[j].end+1){//判断j是否会死 
			//从链表中将其删除 
			next[pred[j]]=next[j];
			pred[next[j]]=pred[j];
			flag=1;
			//判断j的身份
			if(pig[j].id<0)--fsum;
			//判断游戏是否结束
			if(j*fsum==0){
				if(j)printf("MP");
				else printf("FP");
				
				putchar('\n');
				out();
				exit(0);
			}
			//判断是否存在奖励/惩罚
			if(pig[j].id>0&&i==0){
				pig[0].zhuge=0;
				for(int k=9;k--;){
					pig[0].begin[k].succ=pig[0].end+k;
					pig[0].end[k].pred=pig[0].begin+k;
				}
			}
			else if(pig[j].id<0)for(j=3;j--;)got(i,heap[m?--m:0]);
		}
		else{
			del(pig[j].begin[1].succ-pl);
			++pig[j].blood;
		}
	}
}
inline bool require(int i,int j,int p){//pig i向pig j请求一张p,否则pig i将向pig j造成1点伤害 
	if(pig[j].begin[p].succ==pig[j].end+p){
		attack(i,j);
		return 0;
	}
	else{
		del(pig[j].begin[p].succ-pl);
		return 1;
	}
} 
inline void update(int i){//i跳了 
	if(pig[i].id>0&&pig[i].id<3)pig[i].id=3,flag=1;
	else if(pig[i].id<0&&pig[i].id>-3)pig[i].id=-3,flag=1;
}
inline bool find(int i,int flag){//从i开始,寻找身份为flag的猪打出无懈可击;同时认为其献殷勤/表敌意,跳反/忠 
	if(abs(flag)<3)return 0;
	if(pig[i].id*flag>0&&pig[i].begin[7].succ!=pig[i].end+7){
		del(pig[i].begin[7].succ-pl);
		update(i);
		return !find(i,-flag);
	}
	for(int j=next[i];j!=i;j=next[j])
		if(pig[j].id*flag>0&&pig[j].begin[7].succ!=pig[j].end+7){
			del(pig[j].begin[7].succ-pl);
			update(j);
			return !find(j,-flag);
		} 
	return 0;
}
inline void req(int i,int p){//pig i向所有人请求p 
	int blood=pig[0].blood;
	for(int j=next[i];j!=i;j=next[j])
		if(!find(i,pig[j].id))
			require(i,j,p);
	if(pig[0].blood!=blood&&abs(pig[i].id)==2){
		flag=1;
		pig[i].id/=2;
	}
}
int main(){
	int i,j;
	scanf("%d%d",&n,&m);
	//预处理
		//映射 
	f['P']=1,	f['K']=2,	f['D']=3,	f['F']=4,	f['N']=5,	f['W']=6,	f['J']=7,	f['Z']=8;
	revf[1]='P',revf[2]='K',revf[3]='D',revf[4]='F',revf[5]='N',revf[6]='W',revf[7]='J',revf[8]='Z';
		//预处理单向链表,指向下一个还活着的猪。 
	for(i=n;--i;)next[i-1]=i,pred[i]=i-1;
	next[n-1]=0,pred[0]=n-1;
		//预处理猪们的牌表和血量。 
	for(i=n;i--;){
		pig[i].blood=4;
		for(j=9;j--;)pig[i].begin[j].succ=pig[i].end+j,pig[i].end[j].pred=pig[i].begin+j;
	}
	//Read
	for(i=0;isucc){
			switch(ptr->data){
				case 1:
					if(pig[i].blood<4){
						del(ptr-pl);
						++pig[i].blood;
					}
					break;
				case 2:
					if(notyet|pig[i].zhuge&&fuck1+1){
						update(i);
						del(ptr-pl);
						notyet=0;
						require(i,fuck1,3);
					}
					break;
				case 8:
					del(ptr-pl);
					if(pig[i].zhuge==0){
						pig[i].zhuge=1;
						flag=1;
					}
					break;
				case 4:
					if(fuck2!=i){
						del(ptr-pl);
						update(i);
						if(!find(i,pig[fuck2].id)){
							if(i==0&&pig[fuck2].id>0)attack(i,fuck2);
							else
								while(1){
									if(!require(i,fuck2,2))break;
									if(!require(fuck2,i,2))break;
								}
						}
					}
					break;
				case 5:
					del(ptr-pl);
					req(i,2);
					break;
				case 6:
					del(ptr-pl);
					req(i,3);
					break;
			}
			if(flag){
				flag=0;
				fuck1=hate(i,next[i])?next[i]:-1;
				if(pig[i].id<0)fuck2=0;
				else{
					fuck2=next[i];
					while(fuck2!=i&&!hate(i,fuck2))fuck2=next[fuck2];
				}
				ptr=pig[i].begin;
			}
		} 
	}
}


你可能感兴趣的:(Code)