先上题目:

Eight

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 11243    Accepted Submission(s): 3022
Special Judge

Problem Description
The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as:

 1  2  3  4
5 6 7 8
9 10 11 12
13 14 15 x

where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:

 1  2  3  4     1  2  3  4     1  2  3  4     1  2  3  4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
r-> d-> r->

The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.

Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and 
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).

In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three 
arrangement.

 
Input
You will receive, several descriptions of configuration of the 8 puzzle. One description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle

1 2 3 
x 4 6 
7 5 8

is described by this list:

1 2 3 x 4 6 7 5 8

 
Output
You will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Do not print a blank line between cases.
 
Sample Input
2 3 4 1 5 x 7 6 8
 
Sample Output
ullddrurdllurdruldr
 
  题意:经典的八数码,给出当前状态,求出恢复到从小到大排列的顺序的任意一种路径,如果不存在就输出unsolvable。这一题用搜索解决。在看到其他人的题解看到这一题有很多种解法,这里我尝试的是用A*,第一次用A*→_→。
  先说说解法,这一题需要先知道的知识:①对于八数码有解的情况,用当前的八个数字组成的序列,如果逆序对的对数是偶数的话就有解,否则无解,这是判断八数码有没有解的条件。②这里如果选择使用哈希记录状态的话,需要想个不错的方法。这里使用的方法是用康托展开。对于这东西可以自行百度一下。
  这里使用A*,需要注意的是,我们选择扩展的状态是选择f(s)(估值函数)最小的状态。其中在计算g(s)(已使用代价)用的是每扩展一次就加一,h(s)(预估使用代价)是使用每一个位置到达正确位置的哈密顿距离之和来作为预估值。在将状态放入优先队列(OPEN表)的时候根据不同顺序比较g(s),h(s)效果可能不一样。
  A*的本质就是每一次从还没有扩展的状态集合里面选出f(s)最小的那个状态来扩展,感觉看起来就是优先队列版的BFS。
  当然,A*不一定就能提高效率,这就得看估值函数的选取了。
  这一题码了两次,第一次是基本上跟着别人的代码写的,第二次自己写,但还是不得不稍微看一些自己写的代码,主要是对康托展开不是很熟悉。
 
上代码:
 
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define MAX 400002
using namespace std;
typedef struct Node{
int maze[][];
int y,x;
int hash;
int h,g;
bool isok(){
return (<=y && y< && <=x && x<);
} bool operator < (const Node a) const{
if(h>a.h) return ;
if(h==a.h && g>a.g) return ;
return ;
} }Node;
Node s;
const int cantor[] = {,,,,,,,,};
const int target = ;
const int cy[]={,,,-};
const int cx[]={,-,,};
int vis[MAX];
int pre[MAX];
priority_queue<Node> p;
bool check(Node c){
int a[];
int k=,sum=;
for(int i=;i<;i++) for(int j=;j<;j++) a[k++]=c.maze[i][j];
for(int i=;i<k;i++) for(int j=i+;j<k;j++) if(a[i] && a[j] && a[i]>a[j]) sum++;
return !(sum&);
} int getHash(Node c){
int a[];
int k=,h=,sum=;
for(int i=;i<;i++) for(int j=;j<;j++) a[k++]=c.maze[i][j];
for(int i=;i<k;i++){
sum=;
for(int j=;j<i;j++){
if(a[i]<a[j]) sum++;
}
h+=sum*cantor[i];
}
return h;
} int getH(Node c){
int res=;
for(int i=;i<;i++) for(int j=;j<;j++){
res+=abs(i-(c.maze[i][j]-)/)+abs(j-(c.maze[i][j]-)%);
}
return res;
} void astar(){
while(!p.empty()) p.pop();
memset(vis,-,sizeof(vis));
memset(pre,-,sizeof(pre));
Node u,v;
s.h = getH(s);
p.push(s);
vis[s.hash]=-;
while(!p.empty()){
u = p.top();
p.pop();
for(int i=;i<;i++){
v=u;v.y+=cy[i];v.x+=cx[i];
if(!v.isok()) continue;
swap(v.maze[v.y][v.x],v.maze[u.y][u.x]);
if(!check(v)) continue;
v.hash = getHash(v);
if(vis[v.hash]!=-) continue;
vis[v.hash]=i; pre[v.hash]=u.hash;
v.g++;
v.h=getH(v);
p.push(v);
if(v.hash == target) return ; }
} } bool scan(){
char ch[];
if(!gets(ch)) return ;
int k=,l=strlen(ch);
for(int i=;i<;i++) for(int j=;j<;j++){
while(k<l && ch[k]==' ') k++;
if(ch[k]=='x'){
s.maze[i][j]=;
s.y=i; s.x=j;
}
else s.maze[i][j]=ch[k]-'';
k++;
}
return ;
} void printPath(){
string ss;
ss.clear();
int next = target;
while(pre[next]!=-){
if(vis[next]==) ss+='r';
else if(vis[next]==) ss+='l';
else if(vis[next]==) ss+='d';
else ss+='u';
next = pre[next];
}
for(int i=(int)ss.length()-;i>=;i--) putchar(ss[i]);
puts("");
} int main()
{
//freopen("data.txt","r",stdin);
while(scan()){
if(!check(s)){
puts("unsolvable");
}else{
s.hash = getHash(s);
if(s.hash == target){
puts("");
}else{
astar();
printPath();
}
}
}
return ;
}

HDU 1043

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define MAX 400002
using namespace std; const int cantor[] = {,,,,,,,,};
const int target = ;
int vis[MAX],pre[MAX];
int cy[]={,,,-};
int cx[]={,,-,};
typedef struct Node{
int maze[][];
int h,g,y,x;
int hash; bool isok(){
return (<=y && y< && <=x && x<);
} bool islegal(){
int a[],k=,sum=;
for(int i=;i<;i++) for(int j=;j<;j++) a[k++]=maze[i][j];
for(int i=;i<k;i++) for(int j=i+;j<k;j++) if(a[i] && a[j] && a[i]>a[j]) sum++;
return !(sum&);
} bool operator < (const Node o)const{
return h==o.h ? g>o.g : h>o.h;
}
}Node;
Node s;
priority_queue<Node> q; int getHash(Node e){
int a[],k=,res=;
for(int i=;i<;i++) for(int j=;j<;j++) a[k++]=e.maze[i][j];
for(int i=;i<k;i++){
int t=;
for(int j=;j<i;j++) if(a[i]<a[j]) t++;
res+=t*cantor[i];
}
return res;
} int getH(Node e){
int res=;
for(int i=;i<;i++) for(int j=;j<;j++){
res+=abs(i-(e.maze[i][j]-)/)+abs(j-(e.maze[i][j]-)%);
}
return res;
} void astar(){
Node u,v;
while(!q.empty()) q.pop();
memset(vis,-,sizeof(vis));
memset(pre,-,sizeof(pre));
s.g=;
s.h=getH(s);
q.push(s);
vis[s.hash]=-;
while(!q.empty()){
u=q.top();
q.pop();
//cout<<u.hash<<endl;
for(int i=;i<;i++){
v=u;v.y+=cy[i];v.x+=cx[i];
if(v.isok()){
swap(v.maze[v.y][v.x],v.maze[u.y][u.x]);
if(v.islegal()){
v.hash = getHash(v);
if(vis[v.hash]==-){
vis[v.hash]=i;
pre[v.hash]=u.hash;
v.g++; v.h=getH(v);
q.push(v);
if(v.hash == target) return ;
}
} }
}
}
} void printPath(){
string ss="";
int next=target;
while(pre[next]!=-){
switch(vis[next]){
case :ss+='r';break;
case :ss+='d';break;
case :ss+='l';break;
case :ss+='u';break;
}
next=pre[next];
}
for(int i=(int)ss.length()-;i>=;i--) putchar(ss[i]);
putchar('\n');
} bool get(){
char ss[];
if(gets(ss)){
int k=,l=strlen(ss);
for(int i=;i<;i++) for(int j=;j<;j++){
while(k<l && ss[k]==' ') k++;
if(ss[k]=='x'){
s.maze[i][j]=;
s.y=i; s.x=j;
}else s.maze[i][j]=ss[k]-'';
k++;
}
return ;
}
return ; } int main()
{
//freopen("data.txt","r",stdin);
while(get()){
if(s.islegal()){
s.hash = getHash(s);
if(s.hash == target) puts("");
else{
astar();
printPath();
}
}else puts("unsolvable");
}
return ;
}

POJ 1077

 

HDU - 1043 - Eight / POJ - 1077 - Eight的更多相关文章

  1. hdu 1043 pku poj 1077 Eight (BFS + 康拓展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 http://poj.org/problem?id=1077 Eight Time Limit: 1000 ...

  2. HDU 1403 Eight&POJ 1077(康拖,A* ,BFS,双广)

    Eight Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  3. Eight POJ - 1077 HDU - 1043 八数码

    Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...

  4. HDU 1043 & POJ 1077 Eight(康托展开+BFS+预处理)

    Eight Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 30176   Accepted: 13119   Special ...

  5. HDU 1043 & POJ 1077 Eight(康托展开+BFS | IDA*)

    Eight Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 30176   Accepted: 13119   Special ...

  6. HDU 1815, POJ 2749 Building roads(2-sat)

    HDU 1815, POJ 2749 Building roads pid=1815" target="_blank" style="">题目链 ...

  7. HDU 1043 八数码(八境界)

    看了这篇博客的讲解,挺不错的.http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 判断无解的情况(写完七种境界才发现有直接判 ...

  8. POJ-1077 HDU 1043 HDU 3567 Eight (BFS预处理+康拓展开)

    思路: 这三个题是一个比一个令人纠结呀. POJ-1077 爆搜可以过,94ms,注意不能用map就是了. #include<iostream> #include<stack> ...

  9. HDU 1043 Eight(八数码)

    HDU 1043 Eight(八数码) 00 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)   Problem Descr ...

随机推荐

  1. DirectFB学习之移植到nuc972平台 标签: DirectFBlinux图形加速驱动【转】

    本文转载自:http://blog.csdn.net/jxgz_leo/article/details/70137304 [nuc972开发板购买地址,感谢支持](https://shop102749 ...

  2. golang LMDB入门例子——尼玛,LMDB的文档真的是太少了

    使用的是这个库:https://github.com/szferi/gomdb 安装: go get github.com/szferi/gomdb 代码: package main import ( ...

  3. Python yield解析

    Pyhton generators and the yield keyword At a glance,the yield statement is used to define generators ...

  4. (转) 前端模块化:CommonJS,AMD,CMD,ES6

    模块化的开发方式可以提高代码复用率,方便进行代码的管理.通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数.目前流行的js模块化规范有CommonJS.AMD.CMD以及ES6的模块 ...

  5. [转载]MySql事物处理

    事务处理在各种管理系统中都有着广泛的应用,比如人员管理系统,很多同步数据库操作大都需要用到事务处理.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如 ...

  6. 【SQL】CASE与DECODE

    1. case..when case..when语句用于按照条件返回查询结果,如当我们想把emp表的工资按照多少分成几个不同的级别,并分别统计各个级别的员工数.SQL语句如下: select (cas ...

  7. AI:PR的数学表示-传统方法PR

    前言: 接上一篇:AI:模式识别的数学表示 在图像处理PR领域,相对于ANN方法,其他的方法一般称为传统方法.在结构上,几乎所有的PR方法都是可解释的.且任一传统方法,在一定约束下,可以转换为SV近邻 ...

  8. semiautomatic annotated tools

    在进行实验图像取样时,可能会用到大量的标签样本,拍摄大量图片进行手工标注要消耗大量时间,半自动化的标注工具可以节省一些时间. 原文链接:http://blog.sina.com.cn/s/blog_6 ...

  9. (转)Bootstrap 之 Metronic 模板的学习之路 - (2)源码分析之 head 部分

    https://segmentfault.com/a/1190000006684122 下面,我们找个目录里面想对较小的文件来分析一下源码结构,我们可以看到,page_general_help.htm ...

  10. C# 网页内容获取

    private string GetGeneralContent(string strUrl) { string strMsg = string.Empty; try { WebRequest req ...