洛谷 P1379 八数码难题 Label:判重&&bfs
特别声明:紫书上抄来的代码,详见P198
题目描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入输出格式
输入格式:
输入初试状态,一行九个数字,空格用0表示
输出格式:
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
输入输出样例
283104765
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的更多相关文章
- 洛谷 P1379 八数码难题 解题报告
P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...
- 洛谷——P1379 八数码难题
P1379 八数码难题 双向BFS 原来双向BFS是这样的:终止状态与起始状态同时入队,进行搜索,只不过状态标记不一样而已,本题状态使用map来存储 #include<iostream> ...
- 洛谷P1379八数码难题
题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中. 要求解的问题是:给出一种初始布局(初始状态)和目标布局(为 ...
- 洛谷—— P1379 八数码难题
https://daniu.luogu.org/problem/show?pid=1379 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示 ...
- 洛谷P1379 八数码难题
传送门 1.先用dfs枚举9!的全排列,存到hash数组里(类似离散化),因为顺序枚举,就不需要排序了 2.朴素bfs,判重就用二分找hash:如果发现当前状态=要求状态,输出步数结束程序 上代码 # ...
- 洛谷 P1379 八数码难题
题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了 ...
- 洛谷 - P1379 - 八数码难题 - bfs
https://www.luogu.org/problemnew/show/P1379 #include <bits/stdc++.h> using namespace std; #def ...
- 洛谷 P1379 八数码难题 题解
我个人感觉就是一道bfs的变形,还是对bfs掌握不好的人有一定难度. 本题思路: 大体上用bfs搜,用map来去重,在这里只需要一个队列,因为需要较少步数达到的状态一定在步数较多的状态之前入队列. # ...
- 洛谷 P1379 八数码难题(map && 双向bfs)
题目传送门 解题思路: 一道bfs,本题最难的一点就是如何储存已经被访问过的状态,如果直接开一个bool数组,空间肯定会炸,所以我们要用另一个数据结构存,STL大法好,用map来存,直接AC. AC代 ...
随机推荐
- Spring Boot的快速启动和部署
>>关于Spring Boot 这是官网描述的特点: 1.Create stand-alone Spring applications 创建独立的Spring应用 2.Embed Tomc ...
- 移除IIS默认的响应头(转载)
转载地址:http://www.cnblogs.com/dudu/p/iis-remove-response-readers.html 在IIS+ASP.NET的运行环境,默认情况下会输出以下的响应头 ...
- 实现VS2010整合NUnit进行单元测试(转载)
代码编写,单元测试必不可少,简单谈谈Nunit进行单元测试的使用方式: 1.下载安装NUnit(最新win版本为NUnit-2.6.4.msi) http://www.nunit.org/index. ...
- Web框架之Tornado
概述 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了 ...
- makefile基础(GNU)
makefile的核心 targets : prerequisites ; commands... //不分行的情况 targets : prerequisites ...
- JS获取form表单的所有输入值
function getFormQueryString(frmID) { var frmID=document.getElementById(frmID); var i,queryString = & ...
- 不定义JQuery插件,不要说会JQuery 分类: JavaScript 2014-11-24 14:18 155人阅读 评论(0) 收藏
一:导言 有些WEB开发者,会引用一个JQuery类库,然后在网页上写一写$("#"),$("."),写了几年就对别人说非常熟悉JQuery.我曾经也是这样的人 ...
- .NET Expression Tree
Expression Tree 第一个简单的例子. [TestMethod] public void GodTest() { Expression<Func<int, int, int&g ...
- [译] Extending jQuery Part1 Simple extensions
本章包含: JQuery 的起源和目标. 你能扩展JQuery 的那些部分. JQuery 扩展的实例. 如今,JQuery 已经是网络上最受欢迎的JavaScript Library. 1.1 jQ ...
- bootstrap 入门
bootstrap 入门 <!DOCTYPE html> <html> <head lang="en"> <meta charset=&q ...


