(水)POJ-2488字典序dfs

题目大意:给一个p,q分别代表图的行与列数(列在输出时用A,B......表示),规定一个走的规则,求出走遍所有格子且不重复的方法,若有多种答案则输出字典序最小的,无输出impossible。这里的字典序以列优先,即A2<B1。

题目链接:点击打开链接

分析:想要走遍全图很简单,这里棘手的便是要输出字典序最小的一个,由于dfs的特性,我们可以用贪心的思想来遍历,1.每次dfs的入口应该按照先枚举列再枚举行  2.每次dfs在递归时总是有8种走法,我们按照预先设定好的按字典序从小到大的方式来走  。   这样就可以做到第一次走完的是最小字典序的走法了。

直接上代码:

#include<cstdio>
#include<cstring>
using namespace std;
int p,q,kase,T;
int d[8][2]={{-1,-2},{1,-2},{-2,-1},{2,-1},{-2,1},{2,1},{-1,2},{1,2}};  //必须按照此顺序
bool vis[10][10];
bool flag=1;
struct point    
{
	int x,y;
}prv[100];    //记录路径
void print()
{
	printf("Scenario #%d:\n",kase-T);
	for(int i=0;i<p*q;i++)
		printf("%c%d",prv[i].y+'A'-1,prv[i].x);
	printf("\n\n");
}
void dfs(int x,int y,int cur)
{
	prv[cur-1].x=x;
	prv[cur-1].y=y;
	if(!flag) return;
	if(cur==q*p)
	{
		flag=0;
		print();
		return;
	}
	for(int i=0;i<8;i++)
	{
		int fx=x+d[i][0],fy=y+d[i][1];
		if(flag&&!vis[fx][fy]&&fx>=1&&fx<=p&&fy>=1&&fy<=q)
		{
			vis[fx][fy]=1;
			dfs(fx,fy,cur+1);
			vis[fx][fy]=0;
		}
	}
	return;
}
int main()
{
	scanf("%d",&T);
	kase=T;
	while(T--)
	{
		flag=1;
		scanf("%d%d",&p,&q);
		memset(vis,false,sizeof vis);
		for(int j=1;j<=q;j++)    //先枚举列
			for(int i=1;i<=p;i++)
			{
				if(!flag) break;
				vis[i][j]=1;
				dfs(i,j,1);
				vis[i][j]=0;
			}
		if(flag)
		{
			printf("Scenario #%d:\n",kase-T);
			printf("impossible\n\n");
		}
	}
	return 0;
}

你可能感兴趣的:(ACM,DFS,字典序,题解报告)