gym100206E (n*n)的马遍历问题 贪心

来源:互联网 发布:马赛克软件下载 编辑:程序博客网 时间:2024/06/06 01:34

其实马踏棋盘的问题很早就有人提出,且早在1823年,J.C.Warnsdorff就提出了一个有名的算法。在每个结点对其子结点进行选取时,优先选择‘出口’最小的进行搜索,‘出口’的意思是在这些子结点中它们的可行子结点的个数,也就是‘孙子’结点越少的越优先跳,为什么要这样选取,这是一种局部调整最优的做法,如果优先选择出口多的子结点,那出口少的子结点就会越来越多,很可能出现‘死’结点(顾名思义就是没有出口又没有跳过的结点),这样对下面的搜索纯粹是徒劳,这样会浪费很多无用的时间,反过来如果每次都优先选择出口少的结点跳,那出口少的结点就会越来越少,这样跳成功的机会就更大一些。这种算法称为为贪心算法,也叫贪婪算法或启发式算法,它对整个求解过程的局部做最优调整,它只适用于求较优解或者部分解,而不能求最优解。这样的调整方法叫贪心策略,至于什么问题需要什么样的贪心策略是不确定的,具体问题具体分析。实验可以证明马遍历问题在运用到了上面的贪心策略之后求解速率有非常明显的提高,如果只要求出一个解甚至不用回溯就可以完成,因为在这个算法提出的时候世界上还没有计算机,这种方法完全可以用手工求出解来,其效率可想而知。

这道题的起点不是固定的,原来只把(1,1)当起点,结果wa了好几发。只好先暴力计算起点的最大值(x<=8,y<=6)。

#include<bits/stdc++.h>const int INF  = 0x3f3f3f3f;const int Maxn = 255;#define ll long long#define mem(x,y) memset(x,y,sizeof(x))using namespace std;int mp[Maxn][Maxn], cnt = 0, flag = 0;int mx[8] = {2, 2, 1, 1, -2, -2, -1, -1}, my[8] = {1, -1, 2, -2, 1, -1, 2, -2};int door(int x, int y, int n) {  //  计算(x,y)下一步能跳的位置数    int cnt = 0;    for (int i = 0; i < 8; i++) {        int a = x + mx[i], b = y + my[i];        if (a >= 1 && a <= n && b >= 1 && b <= n && mp[a][b] == 0)            cnt++;    }    return cnt;}int MM = 0, NN = 0;void deal(int n) {    if (n > 1 && n < 5) return;    cnt = flag = 0;    for (int tt = 1; tt <= 8; tt++)        for (int xx = 1; xx <= 6; xx++) {            int x = tt, y = xx;            mem(mp, 0);            for (cnt = 1; cnt <= n * n; cnt++) {                mp[x][y] = cnt;                if (cnt == n * n) {                    flag = 1;                    return;                }                if (door(x, y, n) == 0)                    break;                int m = 10, a, b;                for (int i = 0; i < 8; i++) {  // 贪心                    int p = x + mx[i], q = y + my[i];                    if (!(p >= 1 && p <= n && q >= 1 && q <= n && mp[p][q] == 0)) continue;                    int k = door(p, q, n);                    if (k < m) {                        m = k;                        a = p, b = q;                    }                }                x = a, y = b;            }        }}int main() {    freopen("classic.in", "r", stdin);    freopen("classic.out", "w", stdout);    int N;    while (cin >> N) {        deal(N);        if (flag == 0)            printf("No solution.\n");        else {            printf("There is solution:\n");            for (int i = 1; i <= N; i++)                for (int j = 1; j <= N; j++)                    printf("%d%c", mp[i][j], j == N ? '\n' : ' ');        }    }}
原创粉丝点击