kuangbin专题二搜索进阶


注意此处提供了链接

kuangbin专题总
kuangbin专题2

1. 八数码

问题描述

在一个$3×3$的网格中,$1\sim 8$这$8$个数字和一个 X恰好不重不漏地分布在这$3×3$的网格中。
例如:

1 2 3
X 4 6
7 5 8

在游戏过程中,可以把X与其上、下、左、右四个方向之一的数字交换(如果存在)。
我们的目的是通过交换,使得网格变为如下排列(称为正确排列):

1 2 3
4 5 6
7 8 X

例如,示例中图形就可以通过让X先后与右、下、右三个方向的数字交换成功得到正确排列。
交换过程如下:

1 2 3   1 2 3   1 2 3   1 2 3
X 4 6   4 X 6   4 5 6   4 5 6
7 5 8   7 5 8   7 X 8   7 8 X

X与上下左右方向数字交换的行动记录为udlr
现在,给你一个初始网格,请你通过最少的移动次数,得到正确排列。

输入格式

输入占一行,将$3×3$的初始网格描绘出来。
例如,如果初始网格如下所示:

1 2 3 
x 4 6 
7 5 8 

则输入为:1 2 3 x 4 6 7 5 8

输出格式

输出占一行,包含一个字符串,表示得到正确排列的完整行动记录。
如果答案不唯一,输出任意一种合法方案即可。
如果不存在解决方案,则输出 unsolvable

输入样例:
2  3  4  1  5  x  7  6  8 
输出样例

$ullddrurdllurdruldr$

思路

详见该链接

代码

/*八数码问题无解:当且仅当逆序对数量是奇数*/
/*1-8每个数和最终位置的曼哈顿距离之和*/
/*string,map<string,int>*/

#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<unordered_map>

using namespace std;

int dir[4][2]={-1,0,1,0,0,-1,0,1};
char op[4]={'u','d','l','r'};

int f(string state)
{
    int res;
    for(int  i=0;i<state.size();i++)
        if(state[i] !='x')
        {
            int t=state[i]-'1';
            res+=abs(i/3-t/3)+abs(i%3-t%3);
        }
    return res;
}


string bfs(string start)
{
    string end1="12345678x";
    unordered_map<string,int> dist;//当前状态所需要距离
    unordered_map<string,bool> st;//当前状态是否被搜过
    unordered_map<string,pair<string,char>> prev;//记录上一个状态以及接下来的操作
    priority_queue<pair<int,string>,vector<pair<int,string>>,greater<pair<int,string>>> heap;


    heap.push({f(start),start});
    dist[start]=0;
    while(heap.size()>0)
    {
        auto t=heap.top();
        heap.pop();

        string state=t.second;
        
        if(state==end1)
            break;
        if(st[state]!=0)
            continue;
        st[state]=true;

        int step=dist[state];
        int x,y;
        for(int i=0;i<state.size();i++)
            if(state[i]=='x')
            {
                x=i/3;
                y=i%3;
                break;
            }
        string source=state;
        for(int i=0;i<=3;i++)
        {
            int a=x+dir[i][0],b=y+dir[i][1];
            if(a>=0&&a<=2&&b>=0&&b<=2)
            {
                swap(state[x*3+y],state[a*3+b]);
                if(!dist.count(state)||dist[state]>step+1)
                {
                    dist[state]=step+1;
                    prev[state]={source,op[i]};
                    heap.push({dist[state]+f(state),state});

                }
                swap(state[x*3+y],state[a*3+b]);
            }
        }
    }
    string res;
    while(end1!=start)
    {
        res+=prev[end1].second;
        end1=prev[end1].first;
    }
    reverse(res.begin(),res.end());
    return res;
}

int main()
{

    string g,c,seq;
    while(cin >> c)
    {
        g+=c;
        if ( c  != "x" )
            seq+=c;
    }
    //printf("%s\n%s\n%s",g,c,seq);
    int t=0;
    for(int i=0;i<seq.size();i++)
        for(int j=i+1;j<seq.size();j++)
            if(seq[i]>seq[j])
                t++;
    if(t%2==1)
        printf("unsolvable\n");
    else
        cout << bfs(g) << endl;
    return 0;
}

2. 八数码II

问题描述

思路

代码


3. 哈密顿绕行世界问题

问题描述

思路

代码


4. 逃跑

问题描述

思路

代码


5. DNA序列

问题描述

思路

代码


6. 噩梦

问题描述

思路

代码


7. A计划

问题描述

思路

代码


8. 旅行

问题描述

思路

代码


文章作者: 保底不歪抽早柚
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 保底不歪抽早柚 !
评论
  目录