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. PHP pack和unpack函数详解

    pack 压缩资料到位字符串之中. 语法: string pack(string format, mixed [args]...); 返回值: 字符串 函数种类: 资料处理 内容说明 本函数用来将资料 ...

  2. CF962E Byteland, Berland and Disputed Cities

    思路: http://codeforces.com/blog/entry/58869. 实现: #include <bits/stdc++.h> using namespace std; ...

  3. jQuery选择器之属性筛选选择器

    在这么多属性选择器中[attr="value"]和[attr*="value"]是最实用的 [attr="value"]能帮我们定位不同类型 ...

  4. Android利用Socket与硬件通信之智能家居APP

    前几天做一个智能家居APP,硬件段使用的是ESP8266WIFI模块,其实不管是WIFI模块还是蓝牙,通信都是同样一个道理,获取IP和端口来进行通信. 我是通过XCOM v2.0 发送信息,移动端接收 ...

  5. ftp 报错 200 Type set to A

    最近在使用ssis 从ftp服务器抓起文件到本地的时候,发现连接ftp出错 200 Type set to A 解决办法: ftp connection 中 设置UsePassiveMode 为Tru ...

  6. Android(java)学习笔记177: 服务(service)之音乐播放器

    1.我们播放音乐,希望在后台长期运行,不希望因为内存不足等等原因,从而导致被gc回收,音乐播放终止,所以我们这里使用服务Service创建一个音乐播放器. 2.创建一个音乐播放器项目(使用服务) (1 ...

  7. Gym - 100676G Training Camp (状压dp)

    G. Training Camp[ Color: Yellow ]Montaser is planning to train very hard for ACM JCPC 2015; he has p ...

  8. DoveCLL and Resistance(湖北省赛)

    题目 构造一个由串联和并联构成的纯电阻电路,使得该电路的等效电阻为p/q,其中(p,q) = 1.要求输出n,表示节点数,m表示电阻个数,m行每行ui,vi,wi,表示ui和vi之间要连上一个电阻为w ...

  9. 目标检测中bounding box regression

    https://zhuanlan.zhihu.com/p/26938549 RCNN实际包含两个子步骤,一是对上一步的输出向量进行分类(需要根据特征训练分类器):二是通过边界回归(bounding-b ...

  10. 失误1: 把i放到循环体内部,i++失效

    54             while($lines_num_of_whole_table>=1){ 55                 my $i = 1;                 ...