ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【逆向BFS + 康托展开 + 打表】hdu 1043 Eight(八数码问题)

2021-02-07 09:01:04  阅读:246  来源: 互联网

标签:1043 paths hdu 状态 int head state cantor 康托


题目描述:

http://acm.hdu.edu.cn/showproblem.php?pid=1043

 

中文大意:

经典八数码问题。

给定初始状态,要求变换到目标状态并输出移动过程。

目标状态固定为:1 2 3 4 5 6 7 8 x 。

 

思路:

采用逆向 BFS + 康托展开判重 + 打表的方法来做这道题。

八数码问题一共有 9! 种状态,每种状态对应一个 cantor 值。

以目标状态为 BFS 起始状态,搜索这 9! 种状态。

移动过程信息记录在 paths[362880] 数组中。

paths[i] 中的 i :现状态的 cantor 值,

pahts[i].from :前状态的 cantor 值,

paths[i].dir :前状态->现状态的移动方向。

因为是逆向 BFS,所以输出的时候需要反过来,即上对下,左对右。

队列节点记录的是当前八数码状态和 “x” 的位置。

在弹出队列首节点,确定了当前八数码的状态信息后,下一步有 4 种选择:“x” 上下左右移动。

“康托展开”用来计算当前状态的 cantor 值,判断该状态是否已经被访问 visited[cantor]。

 

代码:

#include<bits/stdc++.h>
using namespace std;

struct node{
    int state[9];//当前状态 
    int pos;//"x"的位置 
};

int goal[9];
int start[9] = {1,2,3,4,5,6,7,8,0};

//上下左右 
int dir[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
//逆向 
char dir_str[4] = {'d', 'u', 'r', 'l'};

//Cantor用到的常数 
int factory[] = {1,1,2,6,24,120,720,5040,40320,362880};

bool visited[362880] = {false};
 
struct node2{
    int from;//前状态 
    int dir;//前状态->现状态的移动方向 
}paths[362880];

int Cantor(int state[], int n){
    int result = 0;
    for(int i=0;i<n;i++){
        int counted = 0;
        for(int j=i+1;j<n;j++){
            if(state[i] > state[j]){
                counted++;
            }
        }
        result += counted * factory[n-i-1];
    }
    
    return result;
}

void bfs(){
    node head,next;
    memcpy(head.state, start, sizeof(start));
    head.pos = 8;
    
    int cantor = Cantor(head.state, 9);
    visited[cantor] = true;
    
    paths[cantor].from = -1;
    
    queue<node> q;
    q.push(head);
    
    while(!q.empty()){
        head = q.front();
        q.pop();
        
        int px = head.pos % 3;
        int py = head.pos / 3;
        
        int head_cantor = Cantor(head.state, 9);
        for(int i=0;i<4;i++){    
            int nx = px + dir[i][0];
            int ny = py + dir[i][1];
            
            if(nx >= 0 && nx < 3 && ny >= 0 && ny < 3){
                memcpy(next.state, head.state, sizeof(head.state));
                next.pos = ny * 3 + nx;
                
                swap(next.state[next.pos], next.state[head.pos]);
                
                cantor = Cantor(next.state, 9);
                if(!visited[cantor]){
                    visited[cantor] = true;
                                        
                    paths[cantor].from = head_cantor;
                    paths[cantor].dir = i;
                    
                    q.push(next);
                }
            }
        }
    }
}

void print(int cantor){
    while (paths[cantor].from != -1){
        printf("%c", dir_str[paths[cantor].dir]);
        cantor = paths[cantor].from;
    }
    printf("\n");
}

int main(){
    bfs();
    
    char temp;
    while (cin>>temp){
        goal[0] = temp - '0';
        if(goal[0] > 9){
            goal[0] = 0;
        }
        
        for (int i=1;i<9;i++){
            cin>>temp;
            goal[i] = temp - '0';
            
            if(goal[i] > 9){
                goal[i] = 0;
            }
        }
        
        int cantor = Cantor(goal, 9);
        if (!visited[cantor]){
            cout << "unsolvable" << endl;
        }
        else{
            print(cantor);
        }
    }
} 

 

标签:1043,paths,hdu,状态,int,head,state,cantor,康托
来源: https://www.cnblogs.com/bjxqmy/p/14383845.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有