A Knight's Journey POJ - 2488 回溯

傳送門


題目大意:有一個p行q列的棋盤, 一個馬(走日字)要想把所有的格子跳一遍,可以任意起點,任意終點, 每個格子走一次, 求出可行路徑, 如果有多個求出字典序最小的。其中列座標使用A~Z的大寫字母, 行座標用1 ~10數字表示。

解題思路:既然要把所有的格子走一遍, 那麼必然經過A1. 因此直接從A1走即可。 只要第一個不是A1 那麼一定不是字典序最小的。馬可以走八個方向,爲了保證字典序最小, 搜索的時候用回溯, 然後從字典序最小的開始搜。因此方向數組是定的dx[] = {-1, 1, -2, 2, -2, 2, -1, 1}, dy[] = {-2, -2, -1, -1, 1, 1, 2, 2};  這樣只要找到可行路徑, 一定是字典序最小的。其他就是搜索了, 沒有什麼好說的。


代碼:

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>

using namespace std;

int p, q;
int dx[] = {-1, 1, -2, 2, -2, 2, -1, 1}, 
	dy[] = {-2, -2, -1, -1, 1, 1, 2, 2};
struct NOD
{
	int x, y;
}A[100];

int vis[10][10];


bool dfs(int x, int y, int cnt)
{
	A[cnt-1] = (NOD){x, y};
	if(cnt == p * q)
	{
		return true;
	}
	int xx, yy;
	for(int i=0; i<8; ++i)
	{
		xx = x + dx[i];
		yy = y + dy[i];
		if(xx >= 0 && yy >= 0 && xx < p && yy < q && !vis[xx][yy])
		{
			vis[xx][yy] = 1;
			if(dfs(xx, yy, cnt+1)) return true;
			vis[xx][yy] = 0;
		}
	}
	return false;
}


int main()
{
	int T;
	scanf("%d", &T);
	char s[10] = "ABCDEFGHI";
	for(int Case =1; Case <=T; ++Case)
	{
		scanf("%d%d", &p, &q);
		memset(vis, 0, sizeof vis);
		vis[0][0] = 1;
		printf("Scenario #%d:\n", Case);
		if(dfs(0, 0, 1))
		{
			for(int i=0; i<p*q; ++i)
				printf("%c%d", s[A[i].y], A[i].x+1);
			printf("\n");
		}
		else
		   printf("impossible\n");	
		if(Case != T) printf("\n");
	}

	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章