2020-11-28

5 篇文章 0 订阅

不介意用C++再写一遍(二)
参考不介意用C++再写一遍(一)
在验证从一种状态变化到另一种状态最多须要搜索多少层的时候,初步得到的结论是不超过30层,但验证起来很复杂,时间很长。因此须要一个运算比较快的程序。
从网上找了许多程序,发现有一个程序解答速度很快,就把这个程序修改了,特此感谢AcceptedLee,链接如下:AcceptedLee的博客
主要思路:计算012345678所有组合对目标状态(target)的搜索层次(剔除无解状态),找出那些搜索层次达到或超过30的状态(source),搜索方法采用双向宽搜+哈希。为节省时间,只统计曼哈顿距离不小于20的那些状态。至于20以下的,验证后没有发现搜索层次达到30的,所以省略了。
以下是在这位网友的程序基础上进行修改的程序,再次感谢!

#include <iostream>
#include <queue>
#include<time.h>
using namespace std;

clock_t start, finish;
int cc = 0;
int zero_index;
string b = "087654321";
string target = "123405678";
short has[9876544][2];//第二维一号位置存第七位小于第八位
int d[9][5] = { {2,1,3,-1,-1},{3,0,4,2,-1},{2,1,5,-1,-1},{3,0,4,6,-1},
    {4,1,5,3,7},{3,2,4,8,-1},{2,3,7,-1,-1},{3,6,4,8,-1},{2,5,7,-1,-1} };

struct node {
    int d, step;
    string str;
};
queue<node> q1, q2;

int H(string& s, int a) {
    int x = 0;
    for (int i = 0; i < 7; i++)x = x * 10 + (s[i] - '0');
    if (has[x][s[7] < s[8]] == 0) return has[x][s[7] < s[8]] = a, 0;
    return has[x][s[7] < s[8]];
}

node make(int a, int b, string c) {
    node x;
    x.d = a, x.step = b, x.str = c;
    return x;
}

int bfs(string s) {
    q1.push(make(zero_index, 1, s));
    q2.push(make(4, -1, target));
    H(s, 1);
    H(target, -1);
    int nd, nt;
    string ns;
    while (!q1.empty() && !q2.empty()) {
        if (q1.size() < q2.size()) {
            nd = q1.front().d;
            nt = q1.front().step;
            for (int i = 1; i <= d[nd][0]; i++) {
                ns = q1.front().str;
                swap(ns[nd], ns[d[nd][i]]);
                int x = H(ns, nt + 1);
                if (x == 0)
                    q1.push(make(d[nd][i], nt + 1, ns));
                else if (x < 0) return nt + 1 - x - 2;
            }
            q1.pop();
        }
        else {
            nd = q2.front().d;
            nt = q2.front().step;
            for (int i = 1; i <= d[nd][0]; i++) {
                ns = q2.front().str;
                swap(ns[nd], ns[d[nd][i]]);
                int x = H(ns, nt - 1);
                if (x == 0)
                    q2.push(make(d[nd][i], nt - 1, ns));
                else if (x > 0) return  x - nt + 1 - 2;
            }
            q2.pop();
        }
    }
}

//增加判断是否有解函数
int solution(string sta) {
    int ct = 0;
    for (int i = 0; i < 9; i++) 
        if (sta[i] != '0') 
            for (int j = 0; j < i; j++) 
                if (sta[j] > sta[i]) ct++;
   for (int i = 0; i < 9; i++) 
        if (target[i] != '0') 
            for (int j = 0; j < i; j++) 
                if (target[j] > target[i]) ct++;
    if (ct % 2==0 )return true;
    return false;
}

//增加曼哈顿距离计算函数
int manhattan(string sta) {
    int count = 0;
    for (int i = 0; i < 9; i++) 
        if (sta[i] != '0') 
            for (int j = 0; j < 9; j++) 
                if (sta[j] == target[i]) {
                    count += abs(j % 3 - i % 3) + abs(j / 3 - i / 3);
                    break;
                }
    return count;
}

//增加012345678全组合函数
void pr(string str, int num) {
    if (num ==8){
        for (int i = 0; i <= 9; i++) 
            if (str[i] == '0')zero_index = i;
        if (solution(str) == true) 
            if (manhattan(str) >= 20) {
                
                int temp = bfs(str);
                if (temp >= 30) {
                    cout << "序号" << ++cc <<",";
                    cout << str << ",";
                    cout << "曼哈顿距离为"<<manhattan(str) <<",";
                    cout << "搜索"<< temp <<"层"<< endl;
                }
                while (!q1.empty()) q1.pop();
                while (!q2.empty()) q2.pop();
                memset(has, 0, sizeof(short) * 9876544*2);
            }
        return;
    }
    else{
        for (int i = num; i < str.size(); i++){
            swap(str[num], str[i]);
            pr(str, num + 1);
        }
    }
    return;
}

    int main() {
        start = clock();
        pr(b, 0);
        finish = clock();
        printf("Total elapsed %lf seconds\n", (double)(finish - start) / CLOCKS_PER_SEC);
       
    }

程序运行结果如下:

序号1,086754312,曼哈顿距离为21,搜索30层
序号2,086751324,曼哈顿距离为21,搜索30层
序号3,086724351,曼哈顿距离为20,搜索30层
序号4,086714325,曼哈顿距离为20,搜索30层
序号5,076284351,曼哈顿距离为20,搜索30层
序号6,056874312,曼哈顿距离为21,搜索30层
序号7,056871324,曼哈顿距离为21,搜索30层
序号8,056847321,曼哈顿距离为20,搜索30层
序号9,056814327,曼哈顿距离为20,搜索30层
序号10,046587321,曼哈顿距离为20,搜索30层
序号11,870562341,曼哈顿距离为20,搜索30层
序号12,876504321,曼哈顿距离为24,搜索30层
序号13,876532041,曼哈顿距离为20,搜索30层
序号14,876402351,曼哈顿距离为22,搜索30层
序号15,876302541,曼哈顿距离为24,搜索30层
序号16,876342051,曼哈顿距离为20,搜索30层
序号17,876205341,曼哈顿距离为22,搜索30层
序号18,876201354,曼哈顿距离为24,搜索30层
序号19,876251340,曼哈顿距离为20,搜索30层
序号20,876214350,曼哈顿距离为20,搜索30层
序号21,875602341,曼哈顿距离为20,搜索30层
序号22,875264031,曼哈顿距离为20,搜索30层
序号23,874306521,曼哈顿距离为24,搜索30层
序号24,874326051,曼哈顿距离为21,搜索30层
序号25,874256031,曼哈顿距离为21,搜索30层
序号26,872364051,曼哈顿距离为20,搜索30层
序号27,871204356,曼哈顿距离为20,搜索30层
序号28,860547231,曼哈顿距离为21,搜索30层
序号29,860537421,曼哈顿距离为20,搜索30层
序号30,860527341,曼哈顿距离为20,搜索30层
序号31,860347521,曼哈顿距离为21,搜索30层
序号32,867504231,曼哈顿距离为24,搜索30层
序号33,867502341,曼哈顿距离为24,搜索30层
序号34,867324051,曼哈顿距离为21,搜索30层
序号35,867254031,曼哈顿距离为21,搜索30层
序号36,850764321,曼哈顿距离为20,搜索30层
序号37,856704231,曼哈顿距离为24,搜索30层
序号38,856704123,曼哈顿距离为20,搜索30层
序号39,856703421,曼哈顿距离为20,搜索30层
序号40,856702341,曼哈顿距离为24,搜索30层
序号41,856734021,曼哈顿距离为20,搜索30层
序号42,856407321,曼哈顿距离为22,搜索30层
序号43,856204371,曼哈顿距离为22,搜索30层
序号44,856274031,曼哈顿距离为20,搜索30层
序号45,854706321,曼哈顿距离为24,搜索30层
序号46,852704361,曼哈顿距离为20,搜索30层
序号47,851704326,曼哈顿距离为20,搜索30层
序号48,840756321,曼哈顿距离为20,搜索30层
序号49,840576231,曼哈顿距离为21,搜索30层
序号50,840536721,曼哈顿距离为20,搜索30层
序号51,840376521,曼哈顿距离为21,搜索30层
序号52,846705321,曼哈顿距离为22,搜索30层
序号53,846507312,曼哈顿距离为24,搜索30层
序号54,846507123,曼哈顿距离为20,搜索30层
序号55,846502371,曼哈顿距离为22,搜索30层
序号56,846572310,曼哈顿距离为20,搜索30层
序号57,846517320,曼哈顿距离为20,搜索30层
序号58,846207351,曼哈顿距离为24,搜索30层
序号59,846107325,曼哈顿距离为20,搜索30层
序号60,836502741,曼哈顿距离为20,搜索30层
序号61,826704351,曼哈顿距离为22,搜索30层
序号62,826507341,曼哈顿距离为22,搜索30层
序号63,816204357,曼哈顿距离为20,搜索30层
序号64,786504312,曼哈顿距离为24,搜索30层
序号65,786542310,曼哈顿距离为21,搜索30层
序号66,786521340,曼哈顿距离为21,搜索30层
序号67,786204351,曼哈顿距离为24,搜索30层
序号68,678502341,曼哈顿距离为20,搜索30层
序号69,678204351,曼哈顿距离为20,搜索30层
序号70,576801324,曼哈顿距离为24,搜索30层
序号71,576842310,曼哈顿距离为21,搜索30层
序号72,576821340,曼哈顿距离为21,搜索30层
序号73,546807321,曼哈顿距离为24,搜索30层
序号74,476582310,曼哈顿距离为20,搜索30层
序号75,476208351,曼哈顿距离为20,搜索30层
序号76,376502841,曼哈顿距离为20,搜索30层
序号77,346507821,曼哈顿距离为20,搜索30层
序号78,276581340,曼哈顿距离为20,搜索30层
序号79,246507381,曼哈顿距离为20,搜索30层
Total elapsed 553.262000 seconds

对结果简单分析如下:曼哈顿距离为24时且搜索层次为30的有15种,与我之前使用种子筛选的情况少了2种,参考参考八数码问题——持续更新中(一)
经对比后确定是少了567801234和784306512,经验证后,这两种状态搜索到目标状态只须要28层,证明种子优选法不是万能的,无法确定最少须要多少种子才能搜到最短路径。
以上验证还不够全面,应对‘0’在不同位置进行验证。
target为012345678时的验证情况:

序号1,876543210,曼哈顿距离为20,搜索30层
序号2,876103254,曼哈顿距离为22,搜索30层
序号3,856103247,曼哈顿距离为21,搜索30层
序号4,846503217,曼哈顿距离为21,搜索30层
序号5,836507214,曼哈顿距离为22,搜索30层
序号6,836147250,曼哈顿距离为20,搜索30层
Total elapsed 432.004000 seconds

电脑验证速度还是太慢,无意中发现用手机居然很快,就用手机,结果就不具体呈现了。
target为102345678时的验证情况,发现876503241,846703251,846507231,836574210搜索层次达到31。但经过我前面编写的双向宽搜程序验证和前面提到的网友另外给的一个宽搜+哈希程序验证,都达不到30层,虚惊一场。后续双向宽搜程序还是要改进。
target为120345678时的验证情况,与‘0’在首位情况相似,无超过30层的。
target为123045678时的验证情况,有876504321,856407321,876402351搜索层次达到31,再次验证后仍然达不到30层。
后又验证了‘0’在其他位置情况,情况与前面类似,有超30层的,但再次验证后均没有达到30层。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值