题目链接
http://poj.org/problem?id=2488
思路
题意就是给你p*q的棋盘,行号1~p,列号A~A+q,问你一个马走遍整个棋盘的字典序最小的路径。
那就遍历起点,列优先,行其次,然后深搜,深搜的分支也要列小的优先,列一样的行小的优先。然后把路径保存下来,能行的话直接返回就行。
但是这么玩的话时间复杂度咋一想是 26×26×826×26 了,绝逼超时呀,弄得我一开始根本不敢写…..结果写出来测了下最大数据好像可以秒出…看来应该是马的L形线路限制太大了,分支没有想象中那么多。不过具体时间复杂度我真算不来,有高人会算的话恳请留言指导。
还有就是这题好像有人cout printf混用导致WA了,不过我试了下好像木有什么问题,先留个心眼吧。
AC代码
#include <iostream>
#include <string>
#include <stack>
#include <cstring>
#include <queue>
using namespace std;
int n, p, q;
int dx[] = { -1,1,-2,2,-2,2,-1,1 }, dy[] = { -2,-2,-1,-1,1,1,2,2 };
bool vis[30][30];
int cnt = 1;
deque<string>ans;
bool ok = 0;
void dfs(int i, int j)
{
if (ok)return;
if (cnt == p*q)
{
ok = 1;
return;
}
for (int d = 0; d < 8; ++d)
{
int nx = i + dx[d], ny = j + dy[d];
if (nx >= 0 && ny >= 0 && nx < p && ny < q && !vis[nx][ny])
{
string t;
t += ny + 'A';
t += nx + '1';
vis[nx][ny] = 1;
ans.push_back(t);
cnt++;
dfs(nx, ny);
if (ok)return;
cnt--;
ans.pop_back();
vis[nx][ny] = 0;
}
}
}
int main()
{
cin >> n;
for (int k = 1; k <= n; ++k)
{
cin >> p >> q;
ok = 0;
for (int j = 0; j < q; ++j)
{
for (int i = 0; i < p; ++i)
{
cnt = 1;
while (!ans.empty())ans.pop_back();
memset(vis, 0, sizeof vis);
ans.push_back("A1");
vis[i][j] = 1;
dfs(i, j);
if (ok)break;
}
if (ok)break;
}
cout << "Scenario #" << k << ":\n";
if (ok == 0)
cout << "impossible\n";
else
{
while (!ans.empty())
{
string t = ans.front();
cout << t;
ans.pop_front();
}
cout << "\n";
}
cout << "\n";
}
return 0;
}