UVA - 141 - The Spot Game

题意:给一个棋盘,两个人下棋,规则是可以放棋子,也可以拿棋子,在规定的步数内,谁先让棋盘出现重复谁就输。如果棋盘的两个状态通过旋转可以重合,则这两个状态重复。
思路:1.HASH保存每个状态,每走一步就检查是否重复并保存4个状态(4个方向)。
        2.输出结果。
        3.注意空棋盘的情况,还有一种情况是左转右转相同,所以要一个辅助标记initial。
右转90度:
(i,j)->(j,N-i-1)

左转90度:

 (i,j)->(N-j-1,i)

转180度:
(i,j)->(N-i-1,N-j-1)
#include<stdio.h>
#include<string.h>
#define MAX 100003
int N,step,rear;
int state[MAX][55][55],map[55][55];
int head[MAX],next[MAX];
int hash(int n)
{
	int i,j,v=0;
	for(i=0;i<N;i++)
	{
		for(j=0;j<N;j++)
		{
			v=v*10+state[n][i][j];
			v%=MAX;
		}
	}
	return v%MAX;
}
int isExist(int n)
{
	int h,u;
	h=hash(n);
	u=head[h];
	if(!memcmp(state[u],state[n],sizeof(state[u])))return u;
	while(u)
	{
		if(!memcmp(state[u],state[n],sizeof(state[u])))return u;
		u=next[u];
	}
	next[n]=head[h];
	head[h]=n;
	return -1;
}
int Insert(int x,int y,int value)
{
	int i,j,tag,initial;
	int tmp[55][55];
	map[x][y]=value;
	memcpy(tmp,map,sizeof(map));
	/*Save every state*/
	memcpy(state[rear],tmp,sizeof(tmp));
	if(isExist(rear)>=0)return 0;
	else rear++;
	initial=rear-1;
	/*turn left*/	
	for(i=0;i<N;i++)
	{
		for(j=0;j<N;j++)
		{
			state[rear][i][j]=tmp[j][N-i-1];
		}
	}
	tag=isExist(rear);
	if(tag>=0&&tag<initial)return 0;
	else rear++;
	/*turn right*/
	for(i=0;i<N;i++)
	{
		for(j=0;j<N;j++)
		{
			state[rear][i][j]=tmp[N-j-1][i];
		}
	}
	tag=isExist(rear);
	if(tag>=0&&tag<initial)return 0;
	else rear++;
	/*turn 180 degree*/
	for(i=0;i<N;i++)
	{
		for(j=0;j<N;j++)
		{
			state[rear][i][j]=tmp[N-i-1][N-j-1];
		}
	}
	tag=isExist(rear);
	if(tag>=0&&tag<initial)return 0;
	else rear++;
	return 1;
}
int main()
{
	int x,y,flag,i;
	char c;
	while(scanf("%d",&N)&&N)
	{
		step=1;flag=0;rear=1;
		memset(head,0,sizeof(head));
		memset(state[0],0,sizeof(state[0]));
		memset(state[1],0,sizeof(state[1]));
		memset(map,0,sizeof(map));
		for(i=0;i<2*N;i++)
		{		
			scanf("%d%d %c",&x,&y,&c);
			if(c=='+')
			{
				if(Insert(x-1,y-1,1))step++;
				else 
				{
					printf("Player %d wins on move %d\n",step%2+1,step);	
					flag=1;
					break;
				}
			}
			else
			{
				if(Insert(x-1,y-1,0))step++;
				else 
				{
					printf("Player %d wins on move %d\n",step%2+1,step);	 
					flag=1;
					break;
				}
			}
		}
		if(flag)
		{
			for(;i<2*N-1;i++)
			{
				scanf("%d%d %c",&x,&y,&c);	
			}
		}
		else printf("Draw\n");
	}
	return 0;
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值