题目链接: http://poj.org/problem?id=2488
题意:
棋子按象棋中马的方式在棋盘中跳,给定棋盘的大小,求能使棋子走遍每个棋格且每个棋格只走一次的方案,要求是字典顺序最小的方案。
看到要求字典顺序最小,便单纯的想dfs出所有解然后字典排序。看了解体报告才知道自己多么幼稚......可以先定义好棋子跳动的顺序,使其为字典最小序列。
代码:
#include<iostream>
#include<cstring>
using namespace std ;
int c, r ;
bool b[30][30], bl ;
char str[100] ;
int move[8][2] ={{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}, {2, -1}, {2, 1}} ;
void dfs(int x, int y, int step, int k){
if(bl) return ; //若找到了满足的解,则直接返回
int xi, yi ;
str[k] = 'A' + x ;
str[k+1] = '1' + y ;
if(step==r*c){ //走完全盘则标记成功
bl = true ;
return ;
}
for(int i=0; i<8; i++){
xi = x + move[i][0] ;
yi = y + move[i][1] ;
if(xi>=0&&yi>=0&&xi<r&&yi<c){
if(!b[xi][yi]){
b[xi][yi] = true ;
dfs(xi, yi, step+1, k+2) ;
b[xi][yi] = false ; //回溯
}
}
}
}
int main(){
int n, t = 1 ;
cin >> n ;
while(n--){
cin >> c >> r ;
memset(b, false, sizeof(b)) ;
b[0][0] = true ;
bl = false ;
dfs(0, 0, 1, 0) ;
cout << "Scenario #" << t << ":" << endl ;
if(!bl) cout << "impossible" << endl ;
else{
str[2*r*c] = 0 ; //必须封好字符串!WA了好几次
cout << str << endl ;
}
cout << endl ;
t ++ ;
}
return 0 ;
}
#include<cstring>
using namespace std ;
int c, r ;
bool b[30][30], bl ;
char str[100] ;
int move[8][2] ={{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}, {2, -1}, {2, 1}} ;
void dfs(int x, int y, int step, int k){
if(bl) return ; //若找到了满足的解,则直接返回
int xi, yi ;
str[k] = 'A' + x ;
str[k+1] = '1' + y ;
if(step==r*c){ //走完全盘则标记成功
bl = true ;
return ;
}
for(int i=0; i<8; i++){
xi = x + move[i][0] ;
yi = y + move[i][1] ;
if(xi>=0&&yi>=0&&xi<r&&yi<c){
if(!b[xi][yi]){
b[xi][yi] = true ;
dfs(xi, yi, step+1, k+2) ;
b[xi][yi] = false ; //回溯
}
}
}
}
int main(){
int n, t = 1 ;
cin >> n ;
while(n--){
cin >> c >> r ;
memset(b, false, sizeof(b)) ;
b[0][0] = true ;
bl = false ;
dfs(0, 0, 1, 0) ;
cout << "Scenario #" << t << ":" << endl ;
if(!bl) cout << "impossible" << endl ;
else{
str[2*r*c] = 0 ; //必须封好字符串!WA了好几次
cout << str << endl ;
}
cout << endl ;
t ++ ;
}
return 0 ;
}