10.22A*算法,华容道,状态压缩

news2024/11/23 8:36:09

A*

P1379华容道

问题是要从初始布局用最少的步骤到目标布局,每次只能动0周围的格子,就是华容道;

怎么用算法的思路解决?

状态压缩思路

每个数字就代表当前的状态,队列和map函数都记录的是当前的状态数,

描述一个状态有矩阵形式也有一个数形式

这里c[3][3]是描述状态的矩阵,n就是描述状态的数

这里是把n转化为矩阵形式,并且得到矩阵中0的位置,用f,g记录

执行交换操作无法在数中执行,比较抽象,所以是要转为矩阵,在矩阵里尝试交换,交换完后再转回数的形式进行存储,就是为了节约空间,ns是当前矩阵按当前遍历次序移动完后的结果,

如果在Map里没有出现,就是Map里没有这个数(这个状态),就意味着是新到的状态,由于是bfs,所以必定是到达这个状态的最小步数 

#include<iostream>
#include<map>
#include<queue>
#include<algorithm>
#define ll long long//在这里看到一种很骚的操作:直接把int定义成long long;main函数用signed类型--麻麻再也不怕我忘开long long了!
using namespace std;
const ll dx[]={-1,0,0,1},dy[]={0,-1,1,0};//转移数组;
ll n;
int  main()
{
    cin>>n;
    queue<ll> q;
    q.push(n);
    map<ll,ll> m;
    m[n]=0;
    while(!q.empty())
    {
        int u=q.front(); //初始状态入队列
        int c[3][3],f=0,g=0,n=u;q.pop();
        if(u==123804765)break;
        for(ll i=2;i>=0;i--)
            for(ll j=2;j>=0;j--)
            {
                c[i][j]=n%10,n/=10;
                if(!c[i][j])f=i,g=j;
            }
        for(ll i=0;i<4;i++)
        {
            ll nx=f+dx[i],ny=g+dy[i],ns=0;
            if(nx<0||ny<0||nx>2||ny>2)continue; //越界就不执行
            swap(c[nx][ny],c[f][g]);
            for(ll i=0;i<3;i++)
                for(ll j=0;j<3;j++)ns=ns*10+c[i][j];//矩阵转数列 
            if(!m.count(ns))
            {
                m[ns]=m[u]+1;//map去重的同时顺便统计到达这个状态所需的步数
                q.push(ns);
            }
            swap(c[nx][ny],c[f][g]);//状态复原
        }
    }
    cout<<m[123804765]<<endl; // map的下标直接用数列表示
    return 0;
}

map

map查找

 map操作函数

常用的count(),返回的是出现次数,int型,返回的是键的出现次数,不是键对应的值所以只可能是0或者1

如果是!m.count(n)就表示是没有找到时触发,即此时map里还没有n这个键

m.count(n)就表示找到了这个元素,即map里此时已经有了n这个元素

 

A*方法

 

这一步是在判断当前状态是否还有可能是解,step是当前步数,cnt是估价函数值,cnt的值的确定,是有双重循环,一检测到当前格子里的和解里的不一样,就会++cnt,这循环9次,或者在循环里时就超过限制,就退出了

这个就是判断当前是不是解

 就是说pre是记录上一次到这里来时的方向标号,就意味着不应该再走回去,如果走回去的话,就是先向上(下)走再向下(上)走,先向左(右)走再向右(左)走

可以人为定义状态移动数组,从而满足相反方向的序号具有一定关系

这里是使用对称数组排列,从而使相反方向的序号加和为数组长度-1

所以在递归判断中,是要判断pre+i==3,pre是上一个方向,i是这次选择的方向,加起来为3就是走了回去,需要被剪掉

这个操作虽然不能避免死循环的诞生,比如回字型循环,或者重复状态的出现(避免了只需两步的重复状态,但可能多步回到初始位置),但依然可以避免大量的两步重复

 这里是将输入的字符串(状态压缩的序列)转为矩阵,并得到0的位置

 

是把K作为外层循环,即直接建立在步数限制的基础上判断当前是不是能到达

#include<iostream>
#include<string>
#include<map>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long lt;

int read()
{
    int f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return f*x;
}

char ss[15];
int ans[4][4]=
{{0,0,0,0},
 {0,1,2,3},
 {0,8,0,4},
 {0,7,6,5}};
int a[5][5],k,judge;
int nxtx[]={0,1,-1,0};
int nxty[]={1,0,0,-1};

int check()
{
    for(int i=1;i<=3;++i)
    for(int j=1;j<=3;++j)
    if(ans[i][j]!=a[i][j])return 0;
    return 1;
}

int test(int step)
{
    int cnt=0;
    for(int i=1;i<=3;++i)
    for(int j=1;j<=3;++j)
    if(ans[i][j]!=a[i][j]){ if(++cnt+step>k) return 0;}
    return 1;
}

void A_star(int step,int x,int y,int pre)
{
    if(step==k){ if(check())judge=1; return;}达到当前限制的最大深度
    if(judge) return;
    for(int i=0;i<4;++i)
    {
        int nx=x+nxtx[i],ny=y+nxty[i];
        if(nx<1||nx>3||ny<1||ny>3||pre+i==3) continue;//加入了上述最优性剪枝
        swap(a[x][y],a[nx][ny]);
        if(test(step)&&!judge) A_star(step+1,nx,ny,i);//A*估价合法再向下搜索
        swap(a[x][y],a[nx][ny]);
    }
}

int main()
{
    int x,y;
    scanf("%s",&ss);
    for(int i=0;i<9;++i)
    {
        a[i/3+1][i%3+1]=ss[i]-'0';
        if(ss[i]-'0'==0)x=i/3+1,y=i%3+1;
    }
    if(check()){printf("0");return 0;}//特判不用移动
    while(++k)//枚举最大深度
    {
        A_star(0,x,y,-1);
        if(judge){printf("%d",k);break;}
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1123826.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

众和策略:跨界收购算力公司 高新发展斩获3连板

高新展开23日开盘再度一字涨停&#xff0c;截至发稿&#xff0c;该股报21.74元&#xff0c;涨停板上封单超200万手。至此&#xff0c;该股已连续3个生意日涨停。 公司18日晚间宣布生意预案&#xff0c;拟通过发行股份及支付现金的方式购买高投电子集团持有的华鲲振宇30%股权、…

P1451 求细胞数量 题解

文章目录 题目描述输入格式输出格式样例样例输入样例输出 数据范围与提示思路及部分实现完整代码 题目描述 一矩形阵列由数字 0 0 0 到 9 9 9 组成&#xff0c;数字 1 1 1 到 9 9 9 代表细胞&#xff0c;细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞&#x…

10.23归并排序

课上 归并排序 最大时&#xff0c;就是两个都是完全倒序&#xff0c;但注意一定有一个序列先用完&#xff0c;此时剩一个序列只有一个元素&#xff0c;不用比较&#xff0c;直接加入&#xff0c;所以就是nn-1, 最小时&#xff0c;是都是完全有序&#xff0c;且一个序列中的元…

ZYNQ移植ARM CMSIS_DSP库

移植方法 Vitis中新建一个Application Project&#xff0c;选择HelloWord模板。按下面步骤移植CMSIS_DSP&#xff1a; 下载CMSIS_DSP&#xff0c;拷贝如下文件夹到Vitis工程&#xff1a; SourceIncludePrivateIncludeComputeLibrary (only if you target Neon) 对Source路径下…

古铜色的P1.2直径1.2米无边圆形(饼)创意LED显示屏绽放上海苏河湾万象天地展厅

我们公司的圆形LED显示屏是专门根据业主的独特需求开模定制的。为了满足各种不同的规格和要求&#xff0c;我们已经成功地对多个点间距与直径进行了精密的开模设计&#xff0c;且工艺技术成熟稳定&#xff0c;能够保证快速的交期。 这种圆形LED显示屏是通过独特的开模定制方式…

基础课6——计算机视觉

1.计算机视觉的概念与原理 1.1概念 计算机视觉&#xff08;CV&#xff09;是人工智能的一个重要发展领域&#xff0c;属于计算机科学的一个分支&#xff0c;它企图让计算机能像人类一样通过视觉来获取和理解信息。计算机视觉的应用非常广泛&#xff0c;包括但不限于图像识别、…

HIMA F3236 F7553 面向制造业的可视化人工智能

HIMA F3236 F7553 面向制造业的可视化人工智能 近年来&#xff0c;出现了一种分析高触摸制造的新解决方案:基于图像传感器数据的人工智能驱动分析。与时间和运动研究或Gemba Walks不同&#xff0c;分析从不停止&#xff0c;系统更不容易出现人为错误和偏差。 直到最近&#…

Vue3获取proxy对象的值而不是引用的方式

情景 vue3中定义一个响应式对象&#xff1a; let obj1 reactive({userName:"tom", age:5, hobby:{a:"av",b:"bv"}}); 打印obj1&#xff0c;结果为proxy对象 定义第二个响应式对象&#xff1a; let obj2 reactive({userName:"",ag…

2023年中国二手车交易行业发展历程及趋势分析:整体规模仍保持稳定增长[图]

二手车交易主要内容包括&#xff1a;二手车评估前期工作、技术状况鉴定、寄卖、置换业务、价格评估、交易实务。主要手续包括车务手续、车辆保养维修手续、税费手续。 二手车交易行业分类 资料来源&#xff1a;共研产业咨询&#xff08;共研网&#xff09; 未来&#xff0c;二…

PySide6/PyQt6宝典:新手问题一网打尽!

文章目录 📖 介绍 📖🏡 环境 🏡📒 使用方法 📒📝 常用cmd命令📝 如何使用ui文件📝 主窗口如何调用其它窗口📝 后台执行任务(防止界面卡死)📝 信号与槽📝 如何停止循环任务📝 未完...⚓️ 相关链接 ⚓️💋💋💋💋💋💋📖 介绍 📖 本文

typeerror: Cannot read properties of null (reading ‘emitsOptions‘)报错原因及解决方法

可能导致的原因以及解决方法&#xff1a; 在父组件中子组件名称没有正确引入&#xff1a;检查组件名称和子组件是否正确定义props以及emit的使用在一个空值上去访问属性&#xff1a;可以使用可选链操作符&#xff08;&#xff1f;&#xff09;去检查对象是否为空v-if指令的判断…

零信任特权访问管理

零信任特权访问管理 &#xff08;PAM&#xff09; 是一个安全框架&#xff0c;它结合了基本的零信任原则来保护特权帐户和资源。它要求对尝试访问企业资源的所有用户进行持续验证和授权&#xff0c;以防止未经授权的访问。此强制过程可确保默认情况下永远不会信任用户和设备&am…

MacOS Mojave(苹果14系统) v10.14.6中文离线安装包

MacOS Mojave是一款先进的操作系统&#xff0c;它拥有诸多出色的特性。其中&#xff0c;夜间模式可以根据时间或用户设置自动切换&#xff0c;改变了UI、壁纸和窗口的样式&#xff0c;使界面在夜晚使用时更为舒适。另外&#xff0c;新的堆栈和群组功能让用户能更方便地分类和整…

【BigDecima】不可变的,任意精度的有符号十进制数。

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ BigDecima BigDecima作用及原理 BigDecima作用…

经典卷积神经网络 - LeNet

该模型用于手写的数字识别。 LeNet模型包含了多个卷积层和池化层&#xff0c;以及最后的全连接层用于分类。其中&#xff0c;每个卷积层都包含了一个卷积操作和一个非线性激活函数&#xff0c;用于提取输入图像的特征。池化层则用于缩小特征图的尺寸&#xff0c;减少模型参数和…

Go运算操作符全解与实战:编写更高效的代码!

本文全面探讨了Go语言中的各类运算操作符&#xff0c;从基础的数学和位运算到逻辑和特殊运算符。文章在深入解析每一种运算操作符的工作原理、应用场景和注意事项&#xff0c;以帮助开发者编写更高效、健壮和可读的Go代码。 简介 Go语言&#xff0c;作为一种现代的编程语言&am…

Python实战小项目分享

Python实战小项目包括网络爬虫、数据分析和可视化、文本处理、图像处理、聊天机器人、任务管理工具、游戏开发和网络服务器等。这些项目提供了实际应用场景和问题解决思路&#xff0c;可以选择感兴趣的项目进行实践&#xff0c;加深对Python编程的理解和掌握。在实践过程中&…

CRM销售管理系统是如何进行数据分析的

数据分析可以帮助销售人员挖掘潜在问题&#xff0c;知晓哪些渠道可以带来更多的客户&#xff0c;为日常的销售工作提供科学依据。当然&#xff0c;要做好数据分析不是一件简单的事&#xff0c;利用好销售管理系统是关键。那么CRM销售管理系统是如何进行数据分析的呢&#xff1f…

TCP网络通信

package TCP1;//完成TCP通信的 实现发1收1import java.io.DataOutputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket;public class Client {public static void main(String[] args)throws Ex…

计算属性和侦听属性以及方法有什么区别,本文以计算一个数组中所有偶数的和为例

计算属性(computed)是Vue中的一个特殊属性&#xff0c;它根据依赖的数据进行计算&#xff0c;并返回计算结果。计算属性的值会根据其相关依赖项的变化而自动更新&#xff0c;类似于一个响应式的缓存。计算属性可以用来处理一些复杂的逻辑计算&#xff0c;避免在模板中编写过多的…