先上题目:

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. mysql数据库字符编码修改

    mysql数据库字符编码修改 修改数据库的字符集mysql>use mydb mysql>alter database mydb character set utf8; 创建数据库指定数据 ...

  2. SpringMVC中的 --- 异常处理

    系统异常处理器SimpleMappingExceptionResolver 处理器方法执行过程中,可能会发生异常,不想看到错误黄页,想看到一个友好的错误提示页. 自定义异常处理器 使用异常处理注解

  3. Modern Qt Development: The Top 10 Tools You Should Be Using

    Published Friday October 12th, 2018Leave a comment Posted in Biz Circuit & Dev Loop, C++, QtCrea ...

  4. 在ubuntu中安装photoshop cs6

    对于很多专业的PS高手来说,真心难以找到顺手的且可以完美替代PS的软件,所以我们这里的解决办法就是用wine来安装. 虽然网上有很多的wine安装ps的方法,但是在使用过程往住会发生莫名其妙的崩溃,体 ...

  5. 【BZOJ 1590】 Secret Message

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1590 [算法] 字典树 [代码] #include<bits/stdc++.h ...

  6. Sudoku(dfs)

    http://poj.org/problem?id=2676 填九宫格 思路:将每一行,每一列及每一个3*3块中出现的数字标记上,将可填的空的位置记录下来,枚举1-9,填入合适的数. #include ...

  7. Python 36 死锁现象和递归锁、信号量、Event事件、线程queue

    一:死锁现象和递归锁 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远 ...

  8. 数据通讯与网络 第五版第24章 传输层协议-TCP协议部分要点

    上一博客记录了UDP协议的关键要点,这部分记录TCP协议的关键要点. 24.3 传输控制协议(TRANSMISSION CONTROL PROTOCOL) TCP(Transmission Contr ...

  9. Php.ini文件位置在哪里 Php.ini文件找不到

    转载自:http://www.php100.com/html/php/rumen/2013/0831/26.html [导读] Php ini文件是php的一个配置文件,在windows主机中如果你未 ...

  10. # --with-http_random_index_module模块

    作用: 从目录中随机选取一个随机作为主业 环境 nginx -V 检测是否已经安装了该模块 语法 案例 在/usr/share/nginx下随机创建3个html文件 修改配置文件