特别声明:紫书上抄来的代码,详见P198

题目描述

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

输入输出格式

输入格式:

输入初试状态,一行九个数字,空格用0表示

输出格式:

只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

输入输出样例

输入样例#1:

283104765
输出样例#1:

4

判重一 //set

代码

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<set>//测试
#include<algorithm>
using namespace std;
typedef int state[]; state st[],goal={,,,,,,,,};
int dis[],dx[]={-,,,},dy[]={,,-,}; set<int> vis;
void init_lookup_table(){vis.clear();}
int try_to_insert(int s){
int v=;
for(int i=;i<;i++)v=v*+st[s][i];
if(vis.count(v)) return ;
vis.insert(v);
return ;
} int bfs(){
init_lookup_table();
int front=,rear=;
while(front<rear){
state& s=st[front];
if(memcmp(goal,s,sizeof(s))==)return front; int z;
for(z=;z<;z++) if(!s[z]) break;
int x=z/,y=z%;
for(int d=;d<;d++){
int newx=x+dx[d];
int newy=y+dy[d];
int newz=newx*+newy;
if(newx>=&&newx<&&newy>=&&newy<){
state& t=st[rear];
memcpy(&t,&s,sizeof(s));//Copy
t[newz]=s[z];
t[z]=s[newz];
dis[rear]=dis[front]+;
if(try_to_insert(rear)) rear++;
}
}
front++;
}
return ;
} int main(){
// freopen("01.in","r",stdin);
string s;cin>>s;
for(int i=;i<=;i++)st[][i]=s[i]-''; int ans=bfs();
if(ans>) printf("%d\n",dis[ans]);
else printf("-1\n");
return ;
}

紫书上说stl很慢,但是......

膜拜洛谷测评机

不过这是一个好方法吧.比如状态很多但很分散就可以类比set

判重二 //hash

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<set>//测试
#include<algorithm>
using namespace std;
typedef int state[]; state st[],goal={,,,,,,,,};
int dis[],dx[]={-,,,},dy[]={,,-,}; const int hashsize=;
int head[hashsize],next[hashsize];
void init_lookup_table(){memset(head,,sizeof(head));}
int hash(state& s){
int v=;
for(int i=;i<;i++) v=v*+s[i];
return v%;
}
int try_to_insert(int s){
int h=hash(st[s]);
int u=head[h];
while(u){
if(memcmp(st[u],st[s],sizeof(st[s]))== )return ;
u=next[u];
}
next[s]=head[h];
head[h]=s;
return ;
} int bfs(){
init_lookup_table();
int front=,rear=;
while(front<rear){
state& s=st[front];
if(memcmp(goal,s,sizeof(s))==)return front; int z;
for(z=;z<;z++) if(!s[z]) break;
int x=z/,y=z%;
for(int d=;d<;d++){
int newx=x+dx[d];
int newy=y+dy[d];
int newz=newx*+newy;
if(newx>=&&newx<&&newy>=&&newy<){
state& t=st[rear];
memcpy(&t,&s,sizeof(s));//Copy
t[newz]=s[z];
t[z]=s[newz];
dis[rear]=dis[front]+;
if(try_to_insert(rear)) rear++;
}
}
front++;
}
return ;
} int main(){
// freopen("01.in","r",stdin);
string s;cin>>s;
for(int i=;i<=;i++)st[][i]=s[i]-''; int ans=bfs();
if(ans>) printf("%d\n",dis[ans]);
else printf("-1\n");
return ;
}

震惊!!!

判重三 //编码(只适用于码数很小的情况下,比如30!就不行)

代码

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<set>//测试
#include<algorithm>
using namespace std;
typedef int state[]; state st[],goal={,,,,,,,,};
int dis[],dx[]={-,,,},dy[]={,,-,}; int vis[],fact[];
void init_lookup_table(){
fact[]=;
for(int i=;i<;i++) fact[i]=fact[i-]*i;
}
int try_to_insert(int s){
int code=;//把st[s]映射到整数code
for(int i=;i<;i++){
int cnt=;
for(int j=i+;j<;j++)if(st[s][j]<st[s][i]) cnt++;
code+=fact[-i]*cnt;
}
if(vis[code])return ;
return vis[code]=;
} int bfs(){
init_lookup_table();
int front=,rear=;
while(front<rear){
state& s=st[front];
if(memcmp(goal,s,sizeof(s))==)return front; int z;
for(z=;z<;z++) if(!s[z]) break;
int x=z/,y=z%;
for(int d=;d<;d++){
int newx=x+dx[d];
int newy=y+dy[d];
int newz=newx*+newy;
if(newx>=&&newx<&&newy>=&&newy<){
state& t=st[rear];
memcpy(&t,&s,sizeof(s));//Copy
t[newz]=s[z];
t[z]=s[newz];
dis[rear]=dis[front]+;
if(try_to_insert(rear)) rear++;
}
}
front++;
}
return ;
} int main(){
// freopen("01.in","r",stdin);
string s;cin>>s;
for(int i=;i<=;i++)st[][i]=s[i]-''; int ans=bfs();
if(ans>) printf("%d\n",dis[ans]);
else printf("-1\n");
return ;
}

总结起来就是:效率 hash>编码>set

另外这里有一个详细的转载:http://blog.csdn.net/ouxijv/article/details/7203027

洛谷 P1379 八数码难题 Label:判重&&bfs的更多相关文章

  1. 洛谷 P1379 八数码难题 解题报告

    P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...

  2. 洛谷——P1379 八数码难题

    P1379 八数码难题 双向BFS 原来双向BFS是这样的:终止状态与起始状态同时入队,进行搜索,只不过状态标记不一样而已,本题状态使用map来存储 #include<iostream> ...

  3. 洛谷P1379八数码难题

    题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中. 要求解的问题是:给出一种初始布局(初始状态)和目标布局(为 ...

  4. 洛谷—— P1379 八数码难题

    https://daniu.luogu.org/problem/show?pid=1379 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示 ...

  5. 洛谷P1379 八数码难题

    传送门 1.先用dfs枚举9!的全排列,存到hash数组里(类似离散化),因为顺序枚举,就不需要排序了 2.朴素bfs,判重就用二分找hash:如果发现当前状态=要求状态,输出步数结束程序 上代码 # ...

  6. 洛谷 P1379 八数码难题

    题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了 ...

  7. 洛谷 - P1379 - 八数码难题 - bfs

    https://www.luogu.org/problemnew/show/P1379 #include <bits/stdc++.h> using namespace std; #def ...

  8. 洛谷 P1379 八数码难题 题解

    我个人感觉就是一道bfs的变形,还是对bfs掌握不好的人有一定难度. 本题思路: 大体上用bfs搜,用map来去重,在这里只需要一个队列,因为需要较少步数达到的状态一定在步数较多的状态之前入队列. # ...

  9. 洛谷 P1379 八数码难题(map && 双向bfs)

    题目传送门 解题思路: 一道bfs,本题最难的一点就是如何储存已经被访问过的状态,如果直接开一个bool数组,空间肯定会炸,所以我们要用另一个数据结构存,STL大法好,用map来存,直接AC. AC代 ...

随机推荐

  1. CLR via C#(17)--接口

    CLR不允许继承多个基类,但是可以继承多个接口.凡是能使用具名接口类型的实例的地方,都能使用实现了接口的一个类型的实例. 接口是对一组方法签名进行了统一命名,但不提供任何实现,而具体类则必须为继承的全 ...

  2. JS中级 - 03:文档宽高及窗口事件(选)

    可视区尺寸 document.documentElement.clientWidth document.documentElement.clientHeight 滚动距离 document.body. ...

  3. 数据结构和算法 – 番外篇.时间测试类Timing

    public class Timing { //startingTime--用来存储正在测试的代码的开始时间. TimeSpan startingTime; //duration--用来存储正在测试的 ...

  4. Logcat打印调试信息

    Android Logcat调试中的V.D.I.W.E的分别代表什么? Log.v -- 黑色 -- verbose infoLog.d -- 蓝色 -- debug infoLog.i -- 绿色 ...

  5. 验证备份前设置CONFIGURE CONTROLFILE AUTOBACKUP ON/OFF; 的区别

    关于rman的,环境: oracle 10.2.0 rman nocatalog方式 1.首先设置 CONFIGURE CONTROLFILE AUTOBACKUP ON; 然后进行数据库全备份 RM ...

  6. cordova+angularJS+ionic

    1.创建项目 2.路由 angular.module("starter",['ionic']) // 依赖 ionic 提供的ui-router .config(function ...

  7. java BigInteger使用

    虽然说我不怎么会用java写一些东西,但是java里的biginteger我还是很喜欢的.这个类解决了,我们在其他很多语言中遇到的问题:大数.比如在C++中我们要计算一个大小超过long long的数 ...

  8. 不通过App Store实现ios应用分发下载安装

    最近公司的项目准备着手宣传工作了,宣传手册上要印制App的下载地址二维码,但是客户端应用还未上线,需要一种临时的方案解决应用分发下载问题,通常ios应用必须通过苹果应用商店才能下载安装,但是也可以看到 ...

  9. C/C++面试题

    第一部分:基本概念及其它问答题 1.   关键字static的作用是什么? 这个简单的问题很少有人能回答完全.在C语言中,关键字static有三个明显的作用: 1). 在函数体,一个被声明为静态的变量 ...

  10. Java中的wait和sleep

    sleep()和wait() 首先,Java中的多线程是一种抢占式的机制,而不是分时机制.抢占式的机制是有多个线程处于可运行状态,但是只有一个线程在运行. 这种机制决定了,对于同一对象的多线程访问,必 ...