Sicily 1153: 马的周游问题(DFS+剪枝)

Posted Vincent_Bryan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Sicily 1153: 马的周游问题(DFS+剪枝)相关的知识,希望对你有一定的参考价值。

  这道题没有找到一条回路,所以不能跟1152一样用数组储存后输出。我采用的方法是DFS加剪枝,直接DFS搜索会超时,优化的方法是在搜索是优先走出度小的路径,比如move1和move2都可以走,但是如走了move1后下一步有7种方向可以走,而走了move2后有2种方向可以走,那我们就优先走move2,具体实现参考代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 int _move[8][2] ={{1, -2}, {2, -1}, {2, 1}, {1, 2},{-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}};
  4 
  5 
  6 struct Node{
  7     int x, y;
  8     vector<int>path;
  9 };
 10 Node node;
 11 struct Move{
 12     int x, y;
 13     int degree;
 14 }; 
 15 
 16 void getDegree(Move &move){
 17     int ans = 0;
 18     int cur_x = node.x+ move.x;//下一步的位置 
 19     int cur_y = node.y + move.y;
 20     
 21     for(int i = 0; i < 8; i++){//以cur_x, cur_y为起点,检查其出度 
 22 
 23         int x = cur_x + _move[i][0];
 24         int y = cur_y + _move[i][1];
 25         if(0 <= x && x < 8 && 0 <= y && y < 8){//如果坐标没有越界并且没有重复走过,则出度加一 
 26             int flag = 1;
 27             for(int j = 0; j < node.path.size(); j++){
 28                 if(node.path[j] == x*8 + y){
 29                     flag = 0;
 30                     break;
 31                 }
 32             }
 33             
 34             if(flag)ans++; 
 35         }
 36         
 37     }
 38     move.degree = ans;
 39 }
 40 
 41 bool cmp(Move m1, Move m2){
 42     return m1.degree < m2.degree; 
 43 }
 44 bool dfs(int x, int y){
 45     
 46     node.x = x;
 47     node.y = y;
 48     Move move[8];
 49     for(int i = 0; i < 8; i++){
 50         move[i].x = _move[i][0];
 51         move[i].y = _move[i][1];
 52         if(0 <= node.x + _move[i][0] && node.x + _move[i][0] < 8 && 
 53            0 <= node.y + _move[i][1] && node.y + _move[i][1] < 8)
 54             getDegree(move[i]);    //如果下一步没有越界,则获取它的出度 
 55         else move[i].degree = 100; //若下一步越界,出度设为100 
 56     }
 57     sort(move, move+8, cmp);//对出度从小到大排序 
 58     for(int i = 0; i < 8; i++){
 59             if(move[i].degree == 100) continue;//若出度为100,跳过 
 60             int x = node.x + move[i].x;//下一步位置 
 61             int y = node.y + move[i].y;
 62             if(0 <= x && x < 8 && 0 <= y && y < 8){
 63                 int flag = 1;
 64                 for(int j = 0; j < node.path.size(); j++){
 65                     if(node.path[j] == x*8 + y){
 66                         flag = 0;
 67                         break;
 68                     }
 69                 }    
 70                 if(flag){
 71                     node.path.push_back(x*8 + y);//走下一步 
 72                     
 73                     if(node.path.size() >= 64){//当path的size等于64,则说明已经走遍 
 74                         for(int i = 0; i < node.path.size(); i++){
 75                             cout << node.path[i] + 1 << \' \';
 76                         }
 77                         cout << endl;
 78                         return true;
 79                     }
 80                     if(dfs(x, y))return true;
 81                     node.path.pop_back();//还原到原来 
 82                     node.x -= move[i].x;
 83                     node.y -= move[i].y;    
 84                 }
 85             }
 86             
 87     }
 88     return false;
 89 }
 90 
 91 int main(){
 92     int n;
 93     while(cin >> n && n != -1){
 94         node.path.clear();
 95         n = n-1;
 96         int a = n / 8;
 97         int b = n % 8;
 98         node.path.push_back(a*8 + b);
 99         dfs(a, b);
100     }
101 } 

 

以上是关于Sicily 1153: 马的周游问题(DFS+剪枝)的主要内容,如果未能解决你的问题,请参考以下文章

Python----DFS---骑士周游问题

马踏棋盘(骑士周游问题)

sicily1142(深搜加剪枝)

马的遍历

LQ0107 剪邮票置换+DFS

剪邮票 dfs