您的位置:首页 > 其它

POJ-2488(回溯+剪枝)

2014-06-16 15:15 260 查看
与经典的骑士问题不同之处在于:因为要求字典序最小,所以搜索时我们要保证下一个可以遍历到的点是字典序最小的即可



#include <cstdio>
#include <cstring>

int  M, N;              //M is row(1,2,...), N is col(A,B,...)
bool canBeStart[26][26];//record whether [i][j] can be start
int  total, vis[26][26];//total = M * N, record [i][j]'s visit time(0 ~ total-1)
char path[26 * 2 + 1];  //total path

const int MOVE[8][2] = {
{-1, -2}, {1, -2},
{-2, -1}, {2, -1},
{-2, 1}, {2, 1},
{-1, 2}, {1, 2},

};
bool isOutOfBounds(int r, int c)
{
return r < 0 || r >= M || c < 0 || c >= N;
}
bool dfs(int row, int col, int time)
{
vis[row][col] = time++;
if(time == total) return true;
for(int i = 0; i < 8; ++i){
int r = row + MOVE[i][0], c = col + MOVE[i][1];
if(isOutOfBounds(r, c) || vis[r][c] >= 0) continue;
if(dfs(r, c, time)) return true;
}
vis[row][col] = -1;
return false;
}
bool findPath()
{
//step 1: initialize
total = M * N;
for(int i = 0; i < M; ++i) memset(canBeStart, true, N);
//step 2: dfs at each start point
for(int i = 0; i < M; ++i){
for(int j = 0; j < N; ++j){
if(!canBeStart[i][j]) continue;
for(int k = 0; k < M; ++k) memset(vis[k], 0xFF, N * sizeof(int));
if(dfs(i, j, 0)) return true;
else{//mark centrosymmetric point can not be start
canBeStart[i][j] = false;
canBeStart[M-1-i][j] = false;
canBeStart[i][N-1-j] = false;
canBeStart[M-1-i][N-1-j] = false;
}
}
}
return false;
}
void outputPath()
{
for(int i = 0; i < M; ++i){//row
for(int j = 0; j < N; ++j){//col
int pos = vis[i][j] << 1;
path[pos] = j + 'A';
path[pos+1] = i + '1';
}
}
path[M * N * 2] = '\0';
puts(path);
}

int main()
{
int t, T;

scanf("%d", &T);
for(t = 1; t <= T; ++t){
scanf("%d%d", &M, &N);
printf("Scenario #%d:\n", t);
if(findPath()) outputPath();
else puts("impossible");
puts("");
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: