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 } 
时间: 2024-08-06 03:38:48

Sicily 1153: 马的周游问题(DFS+剪枝)的相关文章

Sicily 1153. 马的周游问题 解题报告

1153_马的周游问题 题目链接: http://soj.me/1153 题目大意: 给定一个8×8棋盘,格子标号1到64,输入一个初始位置的标号,按照马走“日”字的方法,找一条能刚好走完整个棋盘的路径,每个格子恰好只访问过一次. 思路: 用深度优先搜索的方法可以解决问题.首先用二维数组表示整个棋盘,直接用bool类型来表示棋盘的格子是否被访问过.由于输入的是格子的标号,要方便搜索这里用了Point类来表示格子,将序号转化为Point类型.成员ourDegree表示一个点的出度,即这个点可以访问

sicily 1153. 马的周游问题

一.题目描述 在一个8 * 8的棋盘中的某个位置有一只马,如果它走29步正好经过除起点外的其他位置各一次,这样一种走法则称马的周游路线,试设计一个算法,从给定的起点出发,找出它的一条周游路线. 为了便于表示一个棋盘,我们按照从上到下,从左到右对棋盘的方格编号,如下所示: 1     2     3       4     5     6       7     8 9     10       11    12       13    14       15    16 17    18    

Sicily Online Judge 1153.马的周游问题

1153. 马的周游问题 Constraints Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge Description 和题目C同样的任务,这里只是把棋盘扩大到标准的国际象棋.对这样一个8 * 8的棋盘用同样的方法编号如下: 1     2     3       4     5     6       7     8 9     10       11    12       13    14       15    16 17

ZOJ 1008 Gnome Tetravex (DFS + 剪枝)

Gnome Tetravex 题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=8 题意:有N*N个方格,每个方格分为上下左右四个部分,每个部分填数字.现在要求重排方块,使得每两个有边相连的方块对应的数字相同. 思路:就是一个简单的搜索,我想了个剪枝,将上下左右四个方向上每个数字对应的是哪几个方块记录下来,但是这个剪枝并没有起很大的作用,还是T了.后来才发现,如果有很多个方块是相同的,会重复搜索,所以需要将相同的方块一起处

UVA 10318 - Security Panel dfs 剪枝

UVA 10318 - Security Panel dfs 剪枝 ACM 题目地址:UVA 10318 - Security Panel 题意: 这题跟点灯的题目很像,点灯游戏选择一盏灯时会让它以及四周的灯改变状态. 但是我们有特殊的开开关技巧,它给出了改变状态的位置,而不是四周都改变. 问你从全部关着变成全部开着的最小开关步骤. 分析: 很明显,在一个位置上点两次或更多次是没有必要的,所以一个位置只有选择与不选择,用dfs即可,但如果暴力所有可能,复杂度是2^25,会超时,所以要剪枝. 由于

Cubes(DFS+剪枝)

题意:给一个数N,求N最少由多少个数的立方构成,并输出这些数. 做法:DFS + 剪枝,剪枝的边界很很很重要! 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <stdio.h> int cub[400]; int ans[300]; int tp[300]; int n; int sum = 0x3f3f3f3f; //个数 void dfs(int le

hdu 4109 dfs+剪枝优化

求最久时间即在无环有向图里求最远路径 dfs+剪枝优化 从0节点(自己增加的)出发,0到1~n个节点之间的距离为1,mt[i]表示从0点到第i个节点目前所得的最长路径 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<vector> using namespace std; const

POJ 1564 Sum It Up (DFS+剪枝)

 Sum It Up Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5820   Accepted: 2970 Description Given a specified total t and a list of n integers, find all distinct sums using numbers from the list that add up to t. For example, if t = 4

EOJ1981 || POJ1011 经典dfs+剪枝+奇怪的数据

题目:EOJ1981 || POJ1011   经典dfs+剪枝+奇怪的数据 Description George took sticks of the same length and cut them randomly until all partsbecame at most 50 units long. Now he wants to return sticks to the originalstate, but he forgot how many sticks he had origi