c++ 八数码问题增强版



layout: post
title: 八数码问题增强版
subtitle: c++ 八数码问题增强版
date: 2019-08-07
author: dainuofei
header-img: img/post-bg-universe.jpg
catalog: true
tags:
- BFS
---

题目描述

三行三列的数组,其元素值为0至8的数。现有如下的变换规则:

1: 将0与上面一行元素对换

2:将0与下面一行元素对换

3:将0与左面一行元素对换

4:将0与右面一行元素对换

如果已知一个三行三列元素的初始情况,问最少需几次变换,能变换为指定的一种情况?

输入

包括六行的数据,每行有三个以空格分隔的数字。 前三行为原始状态 后三行为目标状态

输出

若能在20次以内(包括20)变换得到目标状态的数组,输出最少的变换次数; 若不能在20次以内(包括20)变换得到目标状态的数组,输出No solution!

样例输入

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

样例输出

10

Hint

(None)

AC代码

#include<iostream>
#include <string.h>
using namespace std;
struct Point//结构体
{
    int a[3][3];
    int step;
};
Point s,t,q[50000];
int f,e;
bool used[9][9][9][9][9][9][9][9];//used[][][][][][][][]是
Point gen(Point u,int type)//这个函数的主要内容就是枚举操作一遍所有的规则 跟 "倒水.cpp" 很相似
{
    int x,y;
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
            if(u.a[i][j]==0)
            {
                x=i,y=j;
                break;
            }
    Point v=u;
    v.step=u.step+1;
    if(type==1&&x>0)//枚举第1种情况
        swap(v.a[x][y],v.a[x-1][y]);//交换上面一行元素
    else if(type==2&&x<2)//枚举第2种情况
        swap(v.a[x][y],v.a[x+1][y]);//将0与下面一行元素对换
    else if(type==3&&y>0)//枚举第3种情况
        swap(v.a[x][y],v.a[x][y-1]);//将0与左面一行元素对换
    else if(type==4&&y<2)//枚举第4种情况
        swap(v.a[x][y],v.a[x][y+1]);//将0与右面一行元素对换
    else
        v.step=-1;//如果交换不到指定的位置,就返回-1
    return v;
}
bool cmp(Point u,Point v)//比较两个结构体是否相同,相同为True 不同为False
{
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
            if(u.a[i][j]!=v.a[i][j])
                return 0;
    return 1;
}
int main()
{
    memset(used,0,sizeof(used));//used是
    for(int i=0;i<3;i++)//输入初始矩阵
        for(int j=0;j<3;j++)
           cin>> s.a[i][j];
    for(int i=0;i<3;i++)//输入期望矩阵
        for(int j=0;j<3;j++)
            cin>>t.a[i][j];
    if(cmp(s,t)==1)//如果他们一样就不用移动
    {
        cout<<0<<endl;//输出0步
        return 0;//退出
    }
    s.step=0;//初始化
    f=1,e=1;//f出队  e入队
    q[1]=s;//把s入队
    used[s.a[0][0]][s.a[0][1]][s.a[0][2]][s.a[1][0]][s.a[1][1]][s.a[1][2]][s.a[2][0]][s.a[2][1]]=1;//把初始矩阵除了5以外的都标为已使用
    while(f<=e)//防止越界
    {
        Point u=q[f++];//u是选定的元素
        for(int i=1;i<=4;i++)//像4个方向拓展
        {
            Point v=gen(u,i);//v是由u按题目上的规则拓展而来的
            if(v.step==-1) continue;//如果无法到达
            if(v.step>20) continue;//如果大于20步
            if(cmp(v,t)==1)//如果和预期的矩阵一样,就输出
            {
                cout<<v.step<<endl;//输出
                return 0;
            }
            if(v.step==20) continue;//如果等于20步
            if (used[v.a[0][0]][v.a[0][1]][v.a[0][2]][v.a[1][0]][v.a[1][1]][v.a[1][2]][v.a[2][0]][v.a[2][1]]==1)//如果初始矩阵除了5以外的都走过
                continue;
            e++;//入队下标+1
            q[e]=v;//入队
            used[v.a[0][0]][v.a[0][1]][v.a[0][2]][v.a[1][0]][v.a[1][1]][v.a[1][2]][v.a[2][0]][v.a[2][1]]=1;//把移完之后的状态保存,设为已经出现过 将来不能再出现
        }
    }
    cout<<"No solution!"<<endl;//无解
    return 0;//返回
}

原文地址:https://www.cnblogs.com/LJA001162/p/11334876.html

时间: 2024-07-31 08:30:44

c++ 八数码问题增强版的相关文章

八数码(map版)

八数码 map真是个奇技淫巧好东西 可以十分简单的实现hash,当然速度就不敢保证了 因为九位数不算很大,完全可以用int存下,所以便将八数码的图像转换成一个int型的数字 #include<iostream> #include<queue> #include<map> #include<algorithm> using namespace std; int d[4]={-3,-1,1,3}; struct node { int position;//用0表

八数码问题强化版:十五数码问题idA*版本

---恢复内容开始--- 上一次介绍过dbfs版本,这次来介绍idA*版本. 首先要理解idA*算法的思想,是将迭代加深与A*的结合,将估价函数h(n)作为迭代的限制值,进行dfs. (A*和迭代加深的介绍等有时间再写出来吧) 对所有点(除0以外的)进行曼哈顿距离计算(目标状态到初始状态),h(n)为当前节点的各点的曼哈顿距离和. 在代码中看: #include<cstdio> #include<algorithm> #include<cstring> #define

136-KC705E 增强版 基于FMC接口的Xilinx Kintex-7 FPGA K7 XC7K325T PCIeX8 接口卡

KC705E 增强版 基于FMC接口的Xilinx Kintex-7 FPGA K7 XC7K325T PCIeX8 接口卡 一.板卡概述 本板卡基于Xilinx公司的FPGAXC7K325T-2FFG900 芯片,pin_to_pin兼容FPGAXC7K410T-2FFG900 ,支持PCIeX8.64bit DDR3容量2GByte,HPC的FMC连接器,板卡支持各种接口输入,软件支持windows,Linux驱动. 二.功能和技术指标:   支持1路PCIe X8 支持PCI Expres

【9018:1368】八数码

1368: 八数码 时间限制: 1 Sec  内存限制: 1024 MB提交: 81  解决: 32[提交][状态][讨论版] 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变. 输入 输入初试状态,一行九个数字,空格用0表示. 输出 只有一行

1225 八数码难题

1225 八数码难题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.问题描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765

HDU 1043 Eight八数码解题思路(bfs+hash 打表 IDA* 等)

题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原为初始状态 思路: 参加网站比赛时拿到此题目,因为之前写过八数码问题,心中暗喜,于是写出一套暴力bfs+hash,结果TLE呵呵 思路一:bfs+hash(TLE) 1 #include <cstdio> 2 #include <cstring> 3 #include <queu

洛谷【P1379】八数码难题

P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变. 输入输出格式 输入格式: 输入初试状态,一行九个数字,空格用0表示 输出格式: 只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊

系统垃圾清理利器CCleaner v5.30.6063绿色单文件版(增强版)

系统垃圾清理利器CCleaner现已更新至v5.30.6063,此次更新为Edge.IE浏览器提供了更好的清理功能,更新了Windows Explorer MRU清理功能,同时改善了应用程序中的SSD检测.5.0版全新Modren UI界面设计,简洁大气!内部框架大优化,性能大提升!支持主动防御及监控! CCleaner是梨子公司Piriform最为著名广受好评的软件,系统垃圾清理工具,免费的系统清理优化和隐私保护工具,也是该公司主打和首发产品!它体积小巧.运行速度极快,具有强大的自定义清理规则

八数码三种用时差距极大的写法

进化史,一种比一种长,一种比一种快.不过第三种似乎还不是最终形态. 第一种,傻逼级迭代加深. 去年十一月写的,那时候刚刚学迭代加深,敲了一个钟头才敲完,codevs上直接过,就没太管,觉得这是个水题.实际上呢,看后文. 1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 int sx,sy,lim,