Sicily 1152. 简单的马周游问题

1152. 简单的马周游问题

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge

Description

在一个5 * 6的棋盘中的某个位置有一只马,如果它走29步正好经过除起点外的其他位置各一次,这样一种走法则称马的周游路线,试设计一个算法,从给定的起点出发,找出它的一条周游路线。

为了便于表示一个棋盘,我们按照从上到下,从左到右对棋盘的方格编号,如下所示:

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

马的走法是“日”字形路线,例如当马在位置 15 的时候,它可以到达 2 4 7 11 19 23 26 28 。但是规定马是不能跳出棋盘外的,例如从位置 1 只能到达 9 14

Input

输入有若干行。每行一个整数N(1<=N<=30),表示马的起点。最后一行用-1表示结束,不用处理。

Output

对输入的每一个起点,求一条周游线路。对应地输出一行,有30个整数,从起点开始按顺序给出马每次经过的棋盘方格的编号。相邻的数字用一个空格分开。

Sample Input

4
-1

Sample Output

注意:如果起点和输入给定的不同,重复多次经过同一方格或者有的方格没有被经过,都会被认为是错误的。

Problem Source

ZSUACM Team Member

跟1153差不多,数据规模小了,可以去看看我的那篇,这里不做多陈述了:

很久之前做的:0.4s,没有优化的DFS:

#include <stdio.h>
#include <string.h>
int h[6][7], st[31], now, go[] = {-2, -1, -2, 1, -1, 2, 1, 2, 2, 1, 2, -1, 1, -2, -1, -2};

void horse(int i, int j, int now) {
    int goi, goj;
    h[i][j] = 1;
    st[now] = i * 6 + j + 1;
    if (now == 29)
        return;
    for (int k = 0; k < 16; k += 2) {
        goi = i + go[k];
        goj = j + go[k + 1];
        if (goi >= 0 && goi <= 4 && goj >= 0 && goj <= 5 && h[goi][goj] == 0)
            horse(goi, goj, now + 1);
    }
    if (st[now + 1] == 0) {
        st[now] = 0;
        h[i][j] = 0;
    }
    return;
}

int main() {
    int n, i, j;
    while (scanf("%d", &n), n != -1) {
        now = 0;
        memset(h, 0, sizeof(h));
        memset(st, 0, sizeof(st));
        i = (n - 1) / 6;
        j = (n - 1) % 6;
        horse(i, j, now);
        printf("%d", st[0]);
        for (i = 1; i < 30; i++)
            printf(" %d", st[i]);
        printf("\n");
    }
    return 0;
}          
然后做了1153之后回头重做此题:0s:

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
using namespace std;

bool is_ok;
int mapp[5][6];
bool vis[5][6];
int ans[30];
int dir[8][2] = {-2,1,-1,2,1,2,2,1,2,-1,1,-2,-1,-2,-2,-1};

void make_map() {
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 6; j++) {
            mapp[i][j] = i * 6 + j + 1;
        }
    }
}

bool is_valid(int i, int j) {
    if (i < 0 || j < 0 || i > 4 || j > 5 || vis[i][j]) {
        return false;
    }
    return true;
}

int cal_roads(int ii, int jj) {//计算下一步有多少条路可以走
    int counter = 0;
    for (int i = 0; i < 8; i++) {
        int next_i = ii + dir[i][0];
        int next_j = jj + dir[i][1];
        if (is_valid(next_i, next_j)) {
            counter++;
        }
    }
    return counter;
}

struct choose {
    int ii;
    int jj;
    int roads;
    choose() {}
    choose(int i, int j) {
        ii = i;
        jj = j;
        roads = cal_roads(i, j);
    }
};

bool cmp(choose a, choose b) {
    return a.roads < b.roads;
}

void DFS(int from_i, int from_j, int num) {
    
    vector<choose> cho;
    for (int i = 0; i < 8; i++) {
        int next_i = from_i + dir[i][0];
        int next_j = from_j + dir[i][1];
        if (is_valid(next_i, next_j)) {
            cho.push_back(choose(next_i, next_j));
        }
    }
    if (cho.empty())//这里千万注意,我忘记了没有路的时候是要返回的,弄了一个下午。。
        return;
    sort(cho.begin(), cho.end(), cmp);
    
    if (num == 29) {
        ans[num] = mapp[cho[0].ii][cho[0].jj];
        is_ok = true;
        return;
    }
    
    for (int i = 0; i < (int)cho.size(); i++) {
        vis[cho[i].ii][cho[i].jj] = true;
        DFS(cho[i].ii, cho[i].jj, num + 1);
        if (is_ok) {
            ans[num] = mapp[cho[i].ii][cho[i].jj];
            return;
        } else {
            vis[cho[i].ii][cho[i].jj] = false;
        }
    }
}

int main() {
    
    int sp;
    make_map();
    
    while (scanf("%d", &sp) && sp != -1) {
        memset(vis, false, sizeof(vis));
        vis[(sp - 1) / 6][(sp - 1) % 6] = true;
        memset(ans, 0, sizeof(ans));
        ans[0] = sp;
        is_ok = false;
        DFS((sp - 1) / 6, (sp - 1) % 6, 1);
        
        for (int i = 0; i < 30; i++) {
            if (i != 0)
                printf(" ");
            printf("%d", ans[i]);
        }
        printf("\n");
    }
        
    return 0;
}             
之后发现一个很好玩的现象,其实我自己编了个程序来找,结果找到了成环的路:


于是乎。。

#include <stdio.h>
int main(){int r[60]={1,14,25,21,29,18,5,16,27,19,8,4,12,23,10,6,17,30,22,26,13,2,15,28,24,11,3,7,20,9},n,i=30;while(i<60)r[i++]=r[i-30];while(scanf("%d",&n)&&n+1)for(i=0;i<30;i++)if(n==r[i]){printf("%d",n);while(r[++i]-n)printf(" %d",r[i]);printf("\n");}return 0;}
好吧我有病。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值