poj1077解题报告详解

在详细的讲解了一下康拓展开和A*搜索后,我们终于迎来了对八数码问题的致命一击,那这里我就秉承之前的解题报告流程,一不要怪我官方啊;;


1.题意:

此题是一个经典的老提,就是给出一个方阵,你要输出基本的路径,使得方阵为1,2,3,4,5,6,7,8,x;

2.思路:

太简单的思路了,就是一个简单的搜索,如果不是会超时,要寻找一个更合适的方案,是不会有人做的;;

3.如何针对超时:

这个问题的解法就是之前讨论的,也就是用A*算法,可以避免广搜的盲目性;

一下附上AC代码,375ms,然后就是哈希判重我感觉没必要,只要在pop时看看是不是close列表中的就可以了,,不需要去判重,可能这就是我使用了A*还是300多ms的愿因吧;;;

#include<iostream>
#include<stdio.h>
#include<queue>
#include<string>
#include<math.h>
#define close -1
using namespace std;
struct node{
    int deep;
    int priority;
    int map[9];
    string path;
    int space;
    friend bool operator < (node a,node b){
        return a.priority > b.priority ;
    }
};
node start,end;
bool visit[368881];
int op[4] = {-3,3,-1,1};
char dir[4] = {'u','d','l','r'};
int jie[10] = {1,1,2,6,24,120,720,5040, 40320, 362880};
int judge(node start){
    for(int i=0;i<9;i++){
        if(start.map[i] != i + 1){
            return false;
        }
    }
    return true;
}
int get_value(int x){
    if(x == 0) return 0;
    if(x == 1) return 1;
    if(x == 2) return 2;
    if(x == 3) return 1;
    return get_value(x-3) + 1;
}
int get_priority(node x){
    int value=0,num;
    for(int i=0;i<9;i++){
        num = fabs(x.map[i] - i -1);
        value += get_value(num);
    }
    return value+x.deep;
}
int canto(node start){
    int num,value=0;
    for(int i=0;i<9;i++){
        num = 0;
        for(int j=i+1;j<9;j++){
            if(start.map[j]<start.map[i]){
                num++;
            }
        }
        value += jie[8-i]*num;
    }
    return value;
}
int BFS(){
    node now,bow;
    priority_queue<node>q;
    q.push(start);
    visit[canto(start)] = 1;
    while(!q.empty()){
        now = q.top();
        int t = canto(now);
        if(visit[t] == close){
            continue;
        }
        q.pop();
        visit[t] = close;
        if(judge(now)){
            end = now;
            return true;
        }
        for(int i=0;i<4;i++){
            bow = now;
            if(i==2&&(bow.space == 3||bow.space == 6)){
                continue;
            }
            if(i==3&&(bow.space == 2||bow.space == 5)){
                continue;
            }
            bow.space = now.space + op[i] ;
            if(bow.space>=0&&bow.space<=8){
                swap(bow.map[bow.space],bow.map[now.space]);
                int c = canto(bow);
                if(visit[c] == close) continue;
                if(visit[c] == 0    ){
                    bow.deep ++;
                    bow.path += dir[i];
                    bow.priority = get_priority(bow);
                    visit[c] = 1;
                    q.push(bow);
                }
            }
        }
    }
    return false;
}
int main(){
    char c;
    for(int z = 0;z < 9;z++){
        c = getchar();
        getchar();
        if(c == 'x'){
            start.space = z;
            start.map[z] = 9;
        }
        else{
            start.map[z] = c - '0';
        }
    }
  //  cout<<"ok"<<endl;
    if(BFS() == 1){
        cout<<end.path<<endl;
    }
    else
        cout<<"unsolveable"<<endl;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值