zoukankan      html  css  js  c++  java
  • hdu 1043 A*

    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 ");
         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(" ");
        }
     return 0;
    }

  • 相关阅读:
    tornado之获取参数
    tornado中命名路由及反向解析使用
    options模块介绍
    服务的启动
    redis操作
    python中使用redis模块, 设置过期时间
    LaTeX
    word 摘要
    常用命令
    机器学习的建议
  • 原文地址:https://www.cnblogs.com/thefirstfeeling/p/4410973.html
Copyright © 2011-2022 走看看