题意:
一个探险队要去参观城市,走n次,每次走1,2,3,4,5,…n步,参观停留的城市,每次方向转90度。路途中有一些障碍物是不能走的,之前拐弯过的点也是不能走的。求所有走法,按字典序输出。
解析:
直接回溯深搜就可以了。
AC代码
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
const int N = 1000;
const int LEN = 500;
const char str[] = "nsew";
// N S W E
const int dx[] = { 1,-1, 0, 0};
const int dy[] = { 0, 0, 1,-1};
string ans[N];
int last, m, tot, path[N];
bool grid[N][N], vis[N][N];
bool can_move(int x, int y, int xx, int yy) {
int from, to;
if(x == xx) {
from = min(y, yy);
to = max(y, yy);
for(int i = from; i <= to; i++)
if(grid[xx][i]) return false;
}else if(y == yy) {
from = min(x, xx);
to = max(x, xx);
for(int i = from; i <= to; i++)
if(grid[i][yy]) return false;
}
return true;
}
void dfs(int x, int y, int dir, int cur) {
if(cur == last) {
if(x == LEN && y == LEN) {
ans[tot] = "";
for(int i = 0; i < last; i++)
ans[tot] += str[path[i]];
tot++;
}
return ;
}
int xx, yy, d;
if(dir == 0 || dir == 1) d = 2;
else d = 0;
for(int i = 0; i < 2; i++) {
xx = x + (cur+1)*dx[d+i];
yy = y + (cur+1)*dy[d+i];
if(!vis[xx][yy] && can_move(x, y, xx, yy)) {
path[cur] = d+i;
vis[xx][yy] = true;
dfs(xx, yy, d+i, cur+1);
vis[xx][yy] = false;
}
}
}
int main() {
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--) {
memset(vis, 0, sizeof(vis));
memset(grid, 0, sizeof(grid));
scanf("%d%d",&last, &m);
int x, y;
for(int i = 0; i < m; i++) {
scanf("%d%d", &x, &y);
grid[y+LEN][x+LEN] = true;
}
tot = 0;
for(int i = 0; i < 4; i++) {
memset(vis, false, sizeof(vis));
path[0] = i;
dfs(LEN+dx[i], LEN+dy[i], i, 1);
}
sort(ans, ans+tot);
for(int i = 0; i < tot; i++) {
puts(ans[i].c_str());
}
printf("Found %d golygon(s).\n\n", tot);
}
return 0;
}