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. CentOS Linux下MySQL 5.1.x的安装、优化和安全配置

    下载页面:http://dev.mysql.com/downloads/mysql/5.1.html#downloads 到页面底部,找到Source downloads,这个是源码版本,下载第1个T ...

  2. 动手实现 React-redux(四):mapDispatchToProps

    在重构 ThemeSwitch 的时候我们发现,ThemeSwitch 除了需要 store 里面的数据以外,还需要 store 来 dispatch: ... // dispatch action ...

  3. Git之删除分支

    目录 删除本地分支 删除远程分支 删除本地分支: git branch -d dev  [git branch -参数 本地分支名称] 删除远程分支: git push origin --delete ...

  4. Android获取本地相册图片、拍照获取图片

    需求:从本地相册找图片,或通过调用系统相机拍照得到图片. 容易出错的地方: 1,当我们指定了照片的uri路径,我们就不能通过data.getData();来获取uri,而应该直接拿到uri(用全局变量 ...

  5. java实现网络监听

    Java实现网络监听 import java.net.*; import java.io.*; public class tcpServer { public static void main(Str ...

  6. Android手机app耗电量测试工具 - Gsam Battery Monitor

    这段时间需要测试一个Android手机app的耗电量,在网上找了一个工具,Gsam Battery Monitor,觉得挺好用,和大家分享一下. 安装app后打开,可以看到主界面是这样的 点击一下上图 ...

  7. XML基本概念及增删改查操作

    一.概念及特征: 1. XML 指可扩展标记语言(Extensible Markup Language),用户可以自己定义标签.XML 被设计用来传输和存储数据,而 HTML 用于格式化并显示数据,并 ...

  8. sublime text3前端开发插件配置以及使用(个人喜爱)

    第一步下载软件接着Ctrl +~ (回车)把下面安装包管理添加到sublimeimport urllib.request,os; pf = 'Package Control.sublime-packa ...

  9. ios水果风暴游戏源码项目下载

    这是一款ios水果风暴游戏源码下载,介绍给大家一下,喜欢的朋友可以下载学习一下吧.应用介绍:这是一个以获得高分和挑战更高难度为目的的游戏.游戏中有九种不同的卡通水果,您可以交换屏幕中两个相邻水果的位置 ...

  10. rmdir

    rmdir——删除空目录 remove empty directories 命令所在路径:bin/rmdir 示例: # rmdir /tmp/japan/longze 删除/tmp/japan/目录 ...