Sicily 1152 简单的马周游问题[Special judge]

深搜,但是要每一步都搜索时要依照下一步能走到的格子数从小到大进行搜索,不然会超时

// Problem#: 1152
// Submission#: 3241599
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
int board[5][6];  //  棋盘 
int path[30];  //  路径最多有30个点 
int dir[8][2] = {{-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}, {-2, 1}};  //  方向 
bool valid(int x, int y) {  //  判断是否访问过以及是否在棋盘内 
    return board[x][y] == false && x >= 0 && x < 5 && y >= 0 && y < 6;
}
int numberOfNextMove(int a, int b) {  //  判断下一步能到达的格子数 
    int total = 0;
    for (int i = 0; i < 8; i++) {
        if (valid(a + dir[i][0], b + dir[i][1])) {
            total++;
        }
    }
    return total;
}
struct node {
    int x, y, sub;
    node() {
        x = y = sub = -1;
    }
    node(int a, int b) {
        x = a;
        y = b;
        sub = numberOfNextMove(a, b);
    }
};
node next(node n, int i) {  //  下一个格子 
    return node(n.x + dir[i][0], n.y + dir[i][1]);
}
bool cmp(node a, node b) {  //  比较下一步能走到的格子数 
    return a.sub < b.sub;
}
node num2node(int n) {  //  数字变为横纵坐标 
    if (valid((n - 1) / 6, (n - 1) % 6)) {
        return node((n - 1) / 6, (n - 1) % 6);
    }
}
int node2num(node n) {  //  横纵坐标变为数字 
    return 6 * n.x + n.y + 1;
}
bool DFS(node cur, int layer) {  //  深搜,cur 为当前节点, layer为已走过的格子数 
    if (layer == 29) {  //  都走过了 
        path[layer] = node2num(cur);  //  加入最后一个路径并返回 
        return true;
    }
    board[cur.x][cur.y] = true;  //  标记当前格子已走过 
    vector<node> v;  //  存储当期格子能走到的格子 
    path[layer] = node2num(cur);
    for (int i = 0; i < 8; i++) {
        node n = next(cur, i);
        if (valid(n.x, n.y)) {
            v.push_back(n);
        }
    }
    sort(v.begin(), v.end(), cmp);  //  按照下一步能走到的格子数排序 
    for (int i = 0; i < v.size(); i++) {
        if (DFS(v[i], layer + 1) == true) {  //  继续以下一个节点为当前节点,layer+1深搜,如果到达终点就返回 
            return true;
        }
    }
    board[cur.x][cur.y] = false;  //  还原当前节点 
    return false;
}
int main() {
    int n;
    while (cin >> n && n != -1) {
        node start = num2node(n);
        DFS(start, 0);
        cout << path[0];
        for (int i = 1; i < 30; i++) {
            cout << " " << path[i];
        }
        cout << endl;
        memset(board, 0, sizeof(board));
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值