搜索算法——六数码

该博客讨论了如何利用搜索算法解决六数码问题,即通过特定变换将初始布局转换为目标布局。博客提供了C++代码实现,使用了map进行判重,并通过队列进行广度优先搜索。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

描述
现有一两行三列的表格如下:

A B C
D E F

把1、2、3、4、5、6六个数字分别填入A、B、C、D、E、F格子中,每个格子一个数字且各不相同。每种不同的填法称为一种布局。如下:

1 3 5
2 4 6
布局1

2 5 6
4 3 1
布局2

定义α变换如下:把A格中的数字放入B格,把B格中的数字放入E格,把E格中的数字放入D格,把D格中的数字放入A格。
定义β变换如下:把B格中的数字放入C格,把C格中的数字放入F格,把F格中的数字放入E格,把E格中的数字放入B格。

问:对于给定的布局,可否通过有限次的α变换和β变换变成下面的目标布局:

1 2 3
4 5 6
目标布局

 
输入
本题有多个测例,每行一个,以EOF为输入结束标志。每个测例的输入是1到6这六个数字的一个排列,空格隔开,表示初始布局ABCDEF格中依次填入的数字。
 
输出
每个输出占一行。可以转换的,打印Yes;不可以转换的,打印No。
 
输入样例
1 3 5 2 4 6
2 5 6 4 3 1
 
输出样例
No
Yes

基本思路:还是套用搜索算法的一般模式。在判重方面,c++得map相当好用啊= =。代码如下,已经经过测试。

#include <iostream>
#include <map>
#include <queue>

using namespace std;

int a[6],key;
map<int, int>findout;
queue<int>q;

void search();
int moveto(int u, int dir);

int main()
{
    findout[123456] = 1;
    //cout << findout[123452] << endl;
    while(cin >> a[0] >> a[1] >> a[2] >> a[3] >> a[4] >> a[5]  )
    {
        search();
        if(key == 1)cout << "Yes" << endl;
        else cout << "No" << endl;
                key = 0;
                findout.clear();
    }
}

void search()
{
    int sum;
    sum = a[0]*100000 + a[1]*10000 + a[2]*1000 + a[3]*100 + a[4]*10 + a[5];
    //cout << sum << endl;
    findout[sum] = 2;
    q.push(sum);

    while(!q.empty())
    {
        int temp;
        temp = q.front();
        q.pop();

        for(int i = 0; i < 2; i++)
        {
            int p;
            p = temp;
            a[0] = p/100000;
            p = p % 100000;
            a[1] = p/10000;
            p = p % 10000;
            a[2] = p/1000;
            p = p % 1000;
            a[3] = p/100;
            p = p % 100;
            a[4] = p/10;
            a[5] = p % 10;
            int v = moveto(temp,i);

            //cout << "temp is" << temp << endl;
            //cout << v << endl;
            if(v == 123456)
            {
                key = 1;
            }
            if(findout[v] == 0)
            {
                findout[v] = 2;
                q.push(v);

            }
        }
    }
}

int moveto(int u, int dir)
{
    int temp;
    switch(dir){
        case 0:
        {
            temp = a[0];
            a[0] = a[3];
            a[3] = a[4];
            a[4] = a[1];
            a[1] = temp;
            break;
        }
        case 1:
        {
             temp = a[1];
            a[1] = a[4];
            a[4] = a[5];
            a[5] = a[2];
            a[2] = temp;
            break;
        }
}

    return (a[0]*100000 + a[1]*10000 + a[2]*1000 + a[3]*100 + a[4]*10 + a[5]);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值