Sicily 1152/1153. 马周游

来源:互联网 发布:国外设计app软件 编辑:程序博客网 时间:2024/06/06 01:44

题目大意:

给出马的初始位置,得出遍历棋盘的一条路径。

解题思路:

DFS(深搜)+剪枝。

1、DFS

I.    计算初始状态root下步可达点

II.   如果下步可达,则继续计算下步的下步是否可达

III.  如果下步不可达,则返回上一步计算其他方向下一步是否可达

IV.  步数不为30,则重复II/III。

2、剪枝

仅仅使用DFS,递归效率低下。

在进行下一步递归时,同时计算下下步可达点数,并按可达点数进行排序。

可达点数少,则意味着进行递归的次数及深度少。

先递归可达点数少的步,在有些情况下可以有效地减少递归时间。


// 1153.马周游 // 遍历之前进行下步可达点计算,并排序// 可达点较少,意味着遍历次数及深度较少 #include <iostream>  #include <vector>#include <memory.h>#include <algorithm>  using namespace std;  struct Position{    int x,y,steps;    };// 数组代替switch计算方向 int move_x[] = {-1, -1, -2, -2, 1, 1, 2, 2};int move_y[] = {-2, 2, 1, -1, 2, -2, 1, -1};int isTouched[10][10];int path[65];// 判断下步是否可达 bool isLegal( const Position p ){    return ( ( p.x >= 1 && p.x <= 8 ) && ( p.y>=1 && p.y <= 8 ) && !isTouched[p.x][p.y] );}// 比较借点下步可达数 bool comp( const Position& p1, const Position& p2 ){    return p1.steps < p2.steps;    } bool movement( Position curr,int step ) {           if( step == 64 ){                   cout << path[0];        for( int i = 1; i < 64; ++i )            cout << " " << path[i];           cout << endl;  // 这有一行空行。。。这也WA。。              return true;    }            vector<Position> nexts;    Position next;    for( int i = 0; i < 8; i++ ){        next.x = curr.x + move_x[i];        next.y = curr.y + move_y[i];        next.steps = 0;                // 如果下一步可达,则计算下一步有多少可达点         if( isLegal(next) ){            Position tmp;            for( int j = 0; j < 8; j++ ){                tmp = next;                tmp.x = next.x + move_x[j];                tmp.y = next.y + move_y[j];                                if( isLegal(tmp) ){                                    next.steps++;                }             }            nexts.push_back(next);           }               }        // 根据下步可达点进行排序     sort(nexts.begin(), nexts.end(), comp);        for( int i = 0; i < nexts.size(); i++ ){        Position next = nexts[i];        isTouched[next.x][next.y] = 1;        path[step] = (next.x - 1)*8 + next.y;             if( movement(next,step+1) ) return true;    // 注意递归结束条件!         isTouched[next.x][next.y] = 0;         }      return false;}int main () {    //freopen("D:\\input.txt","r",stdin);                int start;    Position root,curr,next;        while( cin >> start && start != -1 ){          memset(isTouched,0,sizeof(isTouched));        path[0] = start;                start--;        root.x = start / 8 + 1;        root.y = start % 8 + 1;        isTouched[root.x][root.y] = 1;             movement(root,1);      }          return 0;  }  


原创粉丝点击