洛谷 P1379 八数码难题 解题报告
P1379 八数码难题
题目描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入输出格式
输入格式:
输入初始状态,一行九个数字,空格用0表示
输出格式:
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
虽然这个题没有用到,但还是提一下有解性判断
当棋盘长度是奇数时,有解等价于初始状态与目标状态的抽出来横着放的序列中逆序对个数的奇偶性相同
正常的解题思路:
用康托展开判重,用曼哈顿距离估价搜索
然而我最开始打的记搜wa的不行
最后终于想明白,有环记搜个锤子啊!!!
事实上状态量很少,直接广搜就可以
Code:
#include <cstdio>
#include <cstring>
const int N=1e6;
int s[10],fac[10],step[N],used[N],l,r;
int a[10]={0,2,3,4,9,1,5,8,7,6};
void add(int x){while(x<=9) ++s[x],x+=x&-x;}
int ask(int x){int su=0;while(x) su+=s[x],x-=x&-x;return su;}
struct node
{
int a[10];
}q[N];
int kanton(node x)
{
int ans=0;memset(s,0,sizeof(s));
for(int i=1;i<=9;i++)
ans+=fac[9-i]*(x.a[i]-1-ask(x.a[i])),add(x.a[i]);
return ans;
}
void swap(int &x,int &y){int tmp=x;x=y,y=tmp;}
int main()
{
fac[0]=1;node s;
for(int i=1;i<=9;i++) fac[i]=fac[i-1]*i,s.a[i]=a[i];
int to=kanton(s);
char c[10];scanf("%s",c+1);
for(int i=1;i<=9;i++) s.a[i]=c[i]-'0'+1;
q[0]=s;step[0]=0;
while(l<=r)
{
node now=q[l++];
int id=kanton(now),pos;
if(id==to) {printf("%d\n",step[l-1]);break;}
if(used[id]) continue;used[id]=1;
for(int i=1;i<=9;i++) if(now.a[i]==1) {pos=i;break;}
if(pos%3!=1)
{
node t=now;
swap(t.a[pos],t.a[pos-1]);
q[++r]=t,step[r]=step[l-1]+1;
}
if(pos%3)
{
node t=now;
swap(t.a[pos],t.a[pos+1]);
q[++r]=t,step[r]=step[l-1]+1;
}
if(pos>3)
{
node t=now;
swap(t.a[pos],t.a[pos-3]);
q[++r]=t,step[r]=step[l-1]+1;
}
if(pos<7)
{
node t=now;
swap(t.a[pos],t.a[pos+3]);
q[++r]=t,step[r]=step[l-1]+1;
}
}
return 0;
}
2018.8.30
洛谷 P1379 八数码难题 解题报告的更多相关文章
- 洛谷——P1379 八数码难题
P1379 八数码难题 双向BFS 原来双向BFS是这样的:终止状态与起始状态同时入队,进行搜索,只不过状态标记不一样而已,本题状态使用map来存储 #include<iostream> ...
- 洛谷P1379八数码难题
题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中. 要求解的问题是:给出一种初始布局(初始状态)和目标布局(为 ...
- 洛谷 P1379 八数码难题 Label:判重&&bfs
特别声明:紫书上抄来的代码,详见P198 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给 ...
- 洛谷 P1379 八数码难题
题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了 ...
- 洛谷 - P1379 - 八数码难题 - bfs
https://www.luogu.org/problemnew/show/P1379 #include <bits/stdc++.h> using namespace std; #def ...
- 洛谷—— P1379 八数码难题
https://daniu.luogu.org/problem/show?pid=1379 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示 ...
- 洛谷 P1379 八数码难题(map && 双向bfs)
题目传送门 解题思路: 一道bfs,本题最难的一点就是如何储存已经被访问过的状态,如果直接开一个bool数组,空间肯定会炸,所以我们要用另一个数据结构存,STL大法好,用map来存,直接AC. AC代 ...
- 洛谷P1379 八数码难题
传送门 1.先用dfs枚举9!的全排列,存到hash数组里(类似离散化),因为顺序枚举,就不需要排序了 2.朴素bfs,判重就用二分找hash:如果发现当前状态=要求状态,输出步数结束程序 上代码 # ...
- 洛谷 P1379 八数码难题 题解
我个人感觉就是一道bfs的变形,还是对bfs掌握不好的人有一定难度. 本题思路: 大体上用bfs搜,用map来去重,在这里只需要一个队列,因为需要较少步数达到的状态一定在步数较多的状态之前入队列. # ...
随机推荐
- n点游戏
n点游戏 24点游戏是非常经典而简单的小游戏,从一堆扑克牌中抽取4张,向其中添加运算符号并使其运行结果恰等于24,这叫作24点游戏. 现在我们不再是组合24,而是组合出给定的数字n,但要求只可以利用任 ...
- BZOJ3265: 志愿者招募加强版(线性规划)
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 809 Solved: 417[Submit][Status][Discuss] Descriptio ...
- Spring 中的文件上传与下载控制
先创建根应用上下文配置,WebDemo/src/main/java/com/seliote/webdemo/config/RootContextConfig.java package com.seli ...
- MUI:字符串和json数据的相互转换
JSON.parse()--字符串转换json.JSON.stringify()--json转换成字符串 如:收到Json对象:response,则: {"result":&quo ...
- 2648: SJY摆棋子
2648: SJY摆棋子 https://www.lydsy.com/JudgeOnline/problem.php?id=2648 分析: k-d tree 模板题. 代码: #include< ...
- CSS里一个奇怪的属性
事情是这样的,在一个手机界面的制作中,我发现按钮点击后总会出现一个边框,于是开始搜索解决方案.搜到的解决方案是这样的. a:focus,input:focus{ -webkit-tap-highlig ...
- ios下 active 演示激活
document.body.addEventListener('touchstart', function () { });
- Kotlin的Reified类型:怎样在函数内使用这一类型(KAD 14)
作者:Antonio Leiva 时间:Mar 2, 2017 原文链接:https://antonioleiva.com/reified-types-kotlin/ 对于Java开发者来说,最懊恼的 ...
- MySQL☞where与like
1.无条件查询语句(查询表中所有数据) select * from 表名 2.查询某些列的数据(指定列) select 列名1,列名2,列名3 from 表名 3.条件查询语句 select 列名1, ...
- 第八篇Python基本数据类型之列表、元组与字典
列表 写在最前,必须要会的:append(),extend(),insert(),索引,切片,循环 list 是一个类,是个对象 列表用 方括号[]括起来的,[]内以逗号分割每个元素,列表中的元素可 ...