http://www.cnblogs.com/183zyz/archive/2011/08/12/2135827.html

#include<stdio.h>

#define N 363000

#include<string.h>

#include<queue>

using namespace std;

int visit[N];

char visit1[N];

int pre[N],st,a[10],end;

int dir[9]={1,1,2,6,24,120,720,5040,40320};

struct node {

 int ma[10];//记录状态

 int ans1;//记录状态值

 int x,f,g;

 bool operator <(const node &a)const {

  return a.f<f;

 }

};

int hash(int s[]) {//康拓展开逆序状态值

 int i,j,cnt,sum;

 sum=0;

 for(i=1;i<=9;i++) {

  cnt=0;

  for(j=1;j<i;j++)

   if(s[j]>s[i])cnt++;

   sum+=cnt*dir[i-1];

 }

 return sum;

}

int ABS(int x) {

 return x<0?(-x):x;

}

int h(int s[]) {//不算x时的曼哈顿距离

 int curx,cury,endx,endy,sum,i,ans;

 sum=0;

 for(i=1;i<=9;i++) {

  if(s[i]==9)continue;

  ans=s[i];

  curx=(i+2)/3;//算出当前的行

  cury=(i-1)%3+1;//算出当前的列

  endx=(ans+2)/3;//算出当前位置的值应该在的行

  endy=(ans-1)%3+1;//算出当前位置的值应该在的列

  sum=sum+ABS(curx-endx)+ABS(cury-endy);//算出距离

 }

 return sum;

}

void bfs() {

 int ans,i;

 priority_queue<node>q;

 node cur,next;

 cur.ans1=st=hash(a);//康拓展开查找状态

 visit[cur.ans1]=1;

 if(st==end)

  return;

 for(i=1;i<=9;i++) {//将当前的状态保存下来

  cur.ma[i]=a[i];

  if(a[i]==9)

   cur.x=i;

 }//记录当前的状态

 cur.g=0;//记录深度

 cur.f=h(a);//记录当前的f值

 q.push(cur);//入列

 while(!q.empty()) {

  cur=q.top();//比较f值的大小,选取小的

  q.pop();

  if((cur.x+2)/3!=1) {//向上翻

   next=cur;

   next.x=cur.x-3;//翻转后的位置

   next.ma[cur.x]=next.ma[next.x];//将上方的值存到空格中

   next.ma[next.x]=9;//将上方的值置为空格即‘9’;

   ans=hash(next.ma);//记录翻后的剩余状态

   if(!visit[ans]) {//判断翻转后的状态是否存在

    next.g++;

    next.f=next.g+h(next.ma);////估价函数

    visit[ans]=1;//表示状态值存在

    next.ans1=ans;//将下次状态值记录下来

    pre[ans]=cur.ans1;//将当前状态值记录下来

    visit1[ans]='u';//记录

    if(ans==end)return;

    q.push(next);

   }

  }

   if((cur.x+2)/3!=3) {//向下翻

   next=cur;

   next.x=cur.x+3;

   next.ma[cur.x]=next.ma[next.x];

   next.ma[next.x]=9;

   ans=hash(next.ma);

   if(!visit[ans]) {

    next.g++;

    next.f=next.g+h(next.ma);

    visit[ans]=1;

    next.ans1=ans;

    pre[ans]=cur.ans1;

    visit1[ans]='d';

    if(ans==end) return;

    q.push(next);

   }

  }

    if(cur.x%3!=1) {//向左翻

   next=cur;

   next.x=cur.x-1;

   next.ma[cur.x]=next.ma[next.x];

   next.ma[next.x]=9;

   ans=hash(next.ma);

   if(!visit[ans]) {

    next.g++;

    next.f=next.g+h(next.ma);

    visit[ans]=1;

    next.ans1=ans;

    pre[ans]=cur.ans1;

    visit1[ans]='l';

    if(ans==end)return;

    q.push(next);

   }

  }

     if(cur.x%3!=0) {//向右翻

   next=cur;

   next.x=cur.x+1;

   next.ma[cur.x]=next.ma[next.x];

   next.ma[next.x]=9;

   ans=hash(next.ma);

   if(!visit[ans]) {

    next.g++;

    next.f=next.g+h(next.ma);

    visit[ans]=1;

    next.ans1=ans;

    pre[ans]=cur.ans1;

    visit1[ans]='r';

    if(ans==end)return;

    q.push(next);

   }

  }

 }

}

int check(int s[]) {//剪枝判是否有解

 int i,j,cnt=0;

 for(i=1;i<=9;i++) {

  if(s[i]==9)

   continue;

  for(j=1;j<i;j++) {

   if(s[j]==9)

    continue;

   if(s[j]>s[i])

    cnt++;

  }

 }

 return cnt ;

}

int main() {

 int i,j,ans;

 char str[50];

 while(gets(str)) {

  ans=0;

  memset(visit,0,sizeof(visit));

  for(i=0;str[i];i++) {

   if(str[i]=='x')

    a[++ans]=9;

   else

    if(str[i]!=' ')

     a[++ans]=str[i]-'0';

  }//处理数据

    end=0;

    ans=check(a);//判断是否有解,即ans值必须是偶数才有结果

    if(ans%2) {

     printf("unsolvable\n");

     continue;

    }

    bfs();

    j=0;

    while(end!=st) {//找路径及处理方法

     str[j++]=visit1[end];

     end=pre[end];

    }

    for(i=j-1;i>=0;i--)//输出

     printf("%c",str[i]);

    printf("\n");

    }

 return 0;

}

hdu 1043 A*的更多相关文章

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

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

  2. HDU 1043 Eight(八数码)

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

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

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

  4. HDU - 1043 - Eight / POJ - 1077 - Eight

    先上题目: Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  5. HDU 1043 Eight 八数码问题 A*算法(经典问题)

    HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...

  6. POJ 1077 && HDU 1043 Eight A*算法,bfs,康托展开,hash 难度:3

    http://poj.org/problem?id=1077 http://acm.hdu.edu.cn/showproblem.php?pid=1043 X=a[n]*(n-1)!+a[n-1]*( ...

  7. hdu 1043 Eight 经典八数码问题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 The 15-puzzle has been around for over 100 years ...

  8. 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 ...

  9. HDU 1043 Eight(双向BFS+康托展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...

  10. HDU 1043 Eight(反向BFS+打表+康托展开)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各 ...

随机推荐

  1. js 获取最后一个字符

    方法一: str.charAt(str.length - 1) 方法二: str.subStr(str.length-1,1) 方法三:    var str = "123456" ...

  2. asp.net MVC 错误信息“没有为该对象定义无参数的构造函数”请求各位大神帮忙!

    在做一个登录的功能,没有用MVC自己生成的identity代码,仿照别人的代码写出了以后出现错误. 错误信息如下: 代码如下: 求各位asp.net大神支招,网上找了资料最终也没解决这个问题.

  3. C#中分部类和分部方法的应用

    本篇文章介绍了,C#中分部类和分部方法的应用.需要的朋友参考下     分部类(Partial Class)在C#2.0引入,分部方法(Partial Method)在C#3.0引入,这两个语法特性都 ...

  4. JVM内存各个区域分工简单介绍

    JVM内存各个区域简单介绍: 程序计数器:程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器. 在使用多线程时,为了线程切换后能恢复到正确的执行位置,每条线程都需要有个独立 ...

  5. SQL中的SELECT_简单查询语句总结

    --以scott用户下的dept和emp表为例 --注意:如果scott用户不能使用,请使用system用户登录--解锁scott用户ALTER USER SCOTT ACCOUNT UNLOCK;- ...

  6. DBMS的工作模式

    数据库管理系统(DBMS)是指数据库系统中对数据进行管理的软件系统,它是数据库系统的核心组成部分,对数据库的一切操作(增删改查)都是通过DBMS进行的 DBMS的工作模式如下: 1>接受应用程序 ...

  7. Error:Failed to resolve: com.afollestad:material-dialogs:

    http://www.chenruixuan.com/archives/1068.html 背景: 同事把Android项目直接考给了我...我在Android Studio上运行,然后提示: Err ...

  8. \p{space}|\p{Hex}|\p{Digit}|转译符|\1|\g{-1}|[^ab]|/([^\d\D]+)/

    小骆驼 第七章 漫游正则表达式王国 #!/usr/bin/perl use strict; use warnings; $_ = 'ab \ cde f ghijk10.x12ln'; if(/d/) ...

  9. vue 点击按钮弹窗,点击关闭按钮关闭弹窗。

    <div @click="btnfc()">点击弹窗按钮</div> <div v-show="show"> <div ...

  10. C++知识点总结(纯C++!!)

    1.重载函数是否能够通过函数返回值的类型不同来区分? 不可以.因为在C++编程中,函数的返回值可以忽略(不使用其返回值),程序中调用此时函数名相同和参数相同的两个函数对编译器和程序员来说是没有办法区分 ...