6th Jilin Province Collegiate Programming Contest ——Problem B: Chinese Knight

问题描述:

http://acm.jlu.edu.cn/joj/showproblem.php?pid=2771&off=2700

Problem B: Chinese KnightThere are different pieces In Chinese Chess, such as General, Advisor, Elephant, Knight, Chariot, Cannon and Solider.The knights(horses) are labeled  馬. They begin the game next to the elephants. A  knight moves and captures one point orthogonally and then one point diagonally away from its former position, a move which is traditionally described as being like the Chinese character „日‟. The knight does not jump as the knight does in Western chess. Thus, if there were a piece lying on a point one point away horizontally or vertically from the horse, then the horse's path of movement is blocked and it is unable to move in that direction. Note, however, that a piece two points orthogonally or a single point away diagonally would not impede the movement of the horse. Blocking a horse is also known as "hobbling the horse's leg". The  figure  2.1  illustrates the horse's movement.Since  knight can be blocked, it is sometimes possible to trap the opponent's horse. It is possible for one player's  knight to attack the opponent's horse while the opponent's knight is blocked from attacking, as seen in the figure 2.2.Figure 2.1 Movement of knight Figure 2.2 Asymmetric movementOn a n*n grid chessboard, a Chinese knight want to visit each placement exactly once. This is just like traditional “Knight‟s tour problem”. Unfortunately, there are some obstacles on the placement. The knight can‟t reach it‟s placement and maybe blocked by these obstacles. On the other hand, it is also fortunate, the number of all possible paths is decreased rapidly.Our knight  will always begin his tour at top-left. The number of obstacles is between 1 and 5. You should calculate the number of valid paths. It is not necessary that the knight return his starting position. And all the obstacles is excluded from the path.6th Jilin Province Collegiate Programming Contest - Mar 20, 2012InputThe first line of each case are three integers m, n and k. m and n are the size of chessboard (m, n<=6) and k is indicated the number of obstacles. k is -1 means the end of input.The next k lines are two numbers that are coordinates of each obstacle (startingfrom 1).

OutputFor each case, output the number of all successful paths.

Sample Input5 5 22 35 55 5 -1

Sample Output2

HintOne of possible path of the sample input is described as follows. Each number is the step of knight except -1 means obstacle.1       18      13      6       2312      7        -1      19      1417      2       9       22           58       11      4       15      203       16      21      10       -1

参考代码:

#include<iostream>
using namespace std;


int cB[7][7];
int mark[7][7];
int m,n,k;
int wn;


void initial()
{
	for(int i=0;i<7;i++)
		for(int j=0;j<7;j++)
		{
			cB[i][j]=0;
			mark[i][j]=0;
		}
}


void refresh(int max)
{
	for(int i=1;i<=m;i++)
		for(int j=1;j<=n;j++)
			if(cB[i][j]>max)
			{
				cB[i][j]=0;
				mark[i][j]=0;
			}
}


bool check()
{
	for(int i=1;i<=m;i++)
		for(int j=1;j<=n;j++)
			if(cB[i][j]==0)
				return false;
	return true;
}


void fWay(int px,int py,int no)
{
	cB[px][py]=no;
	
	int flag=false;
	while(mark[px][py]<8)
	{
		if(flag)
		{
			refresh(cB[px][py]);
			flag=false;
		}
		if(mark[px][py]==0)
		{
			mark[px][py]++;
			if((px-2)>0&&(py-1)>0&&cB[px-1][py]!=-1&&cB[px-2][py-1]==0)
			{
				fWay(px-2,py-1,++no);
				flag=true;
			}
		}
		else if(mark[px][py]==1)
		{
			mark[px][py]++;
			if((px-1)>0&&(py-2)>0&&cB[px][py-1]!=-1&&cB[px-1][py-2]==0)
			{
				fWay(px-1,py-2,++no);
				flag=true;
			}
		}
		else if(mark[px][py]==2)
		{
			mark[px][py]++;
			if((px+1)<=m&&(py-2)>0&&cB[px][py-1]!=-1&&cB[px+1][py-2]==0)
			{
				fWay(px+1,py-2,++no);
				flag=true;
			}
		}
		else if(mark[px][py]==3)
		{
			mark[px][py]++;
			if((px+2)<=m&&(py-1)>0&&cB[px+1][py]!=-1&&cB[px+2][py-1]==0)
			{
				fWay(px+2,py-1,++no);
				flag=true;
			}
		}
		else if(mark[px][py]==4)
		{
			mark[px][py]++;
			if((px+2)<=m&&(py+1)<=n&&cB[px+1][py]!=-1&&cB[px+2][py+1]==0)
			{
				fWay(px+2,py+1,++no);
				flag=true;
			}
		}
		else if(mark[px][py]==5)
		{
			mark[px][py]++;
			if((px+1)<=m&&(py+2)<=n&&cB[px][py+1]!=-1&&cB[px+1][py+2]==0)
			{
				fWay(px+1,py+2,++no);
				flag=true;
			}
		}
		else if(mark[px][py]==6)
		{
			mark[px][py]++;
			if((px-1)>0&&(py+2)<=n&&cB[px][py+1]!=-1&&cB[px-1][py+2]==0)
			{
				fWay(px-1,py+2,++no);
				flag=true;
			}
		}
		else if(mark[px][py]==7)
		{
			mark[px][py]++;
			if((px-2)>0&&(py+1)<=n&&cB[px-1][py]!=-1&&cB[px-2][py+1]==0)
			{
				fWay(px-2,py+1,++no);
				flag=true;
			}
		}
	}
	refresh(cB[px][py]);
	if(check())
		wn++;
}


int main()
{
	cin>>m>>n>>k;
	while(k!=-1)
	{
		initial();


		for(int i=0;i<k;i++)
		{
			int x,y;
			cin>>x>>y;
			cB[x][y]=-1;
		}


		wn=0;
		cB[1][1]=1;


		fWay(1,1,1);
		cout<<wn<<endl;


		cin>>m>>n>>k;
	}
	return 0;
}



说明:由于本人菜鸟,代码虽然实现了,但是不好,时间空间占用超多,稍后会给出改进!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值