HDU1043逆向bfs打表

http://acm.hdu.edu.cn/showproblem.php?pid=1043

因为结果都是“12345678x”,目标状态固定,所以可以列举所有的可能,然后用哈希表标志,然后直接调用

/*
PKUoj
Source Code

Problem: 1077        User: 297752873
Memory: 6728K        Time: 313MS
Language: C        Result: Accepted
Source Code
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define QueueSize 370000
int f[8] = {1, 2, 6, 24, 120, 720, 5040, 40320};//用于全排列的哈希函数的构建 
char end[10],ch[4]={'d','u','r','l'};//开始和结束的状态 
int ans[400000],hash[400000];//开始和结束的点 
struct eight
{
       char str[10];//结点矩阵 
       int k ;//空格的位置 
       int fx;//移动的方向1表示上,2表示下, 3表示左,4表示右
       int fa;//父节点   
}s[370000];
typedef struct
{
    int front;
    int rear;
    int count;
    int data[370000];
}CirQueue;
    CirQueue Q;//使用队列,队列里保存的是各状态的下标 

void InitQueue(CirQueue *Q)//建队 
{
    Q->front=Q->rear=0;
    Q->count=0;
}
int QueueEmpty(CirQueue *Q)//判队是否空 
{
    return Q->count==0;
}
void EnQueue(CirQueue *Q,int x)//入队 
{ 
    
        Q->count++;
        Q->data[Q->rear]=x;
        Q->rear=(Q->rear+1)%QueueSize;

}
int DeQueue(CirQueue *Q)//出队,并删除队首元素 
{
    int temp;
        temp=Q->data[Q->front];
        Q->count--;
        Q->front=(Q->front+1)%QueueSize;
        return temp;
}

int get_hash_code(char str[]) //计算全排列哈希值 
{  
    int i, j;  
    int ret = 0, cnt;  
    for(i = 1; i < 9; ++i)  
    {  
        cnt = 0;  
        for(j = 0; j < i; ++j)  
            if(str[j] > str[i])  
                cnt++;  
        ret += cnt*f[i-1];  
    }  
    return ret;  
}  
void print(int x)//若发现可完成,则利用父节点逐个输出 
{
     //printf("find\n");
            while (x!=s[x].fa)
            {
                printf("%c",ch[s[x].fx-1]);
                x=s[x].fa;
            }
            printf("\n");
} 
int bfs()
{
    int w,k,has;
    char temp,a[10];//这些作为中间量 
    memset(hash,0,sizeof(hash));
    has=get_hash_code("123456780");
    s[has].fa=has;//第一个的父节点赋为自己 
    strcpy(s[has].str,"123456780");
    s[has].k=8;    
    hash[has]=1;
    InitQueue(&Q);
    /*if(strcmp(s[beginf].str,end)==0)
    {
       printf("lr\n");
       return 0;
    }*/
    EnQueue(&Q,has);
    while(!QueueEmpty(&Q))
    {
        w=DeQueue(&Q);//取队首元素 
       /* if(strcmp(s[w].str,end)==0)
        {
           print(w);
           return 0;
        } */
        strcpy(a,s[w].str);
           k=s[w].k;//保留空格的位置 
           if (k>=3)//可上移的 
            {
                temp=a[k];a[k]=a[k-3];a[k-3]=temp;
                has=get_hash_code(a);
                if (hash[has]==0)
                {
                    strcpy(s[has].str,a);
                    s[has].fx=1;
                    s[has].fa=w;
                    s[has].k=k-3;
                    hash[has]=1;
                    EnQueue(&Q,has);
                }
                temp=a[k];a[k]=a[k-3];a[k-3]=temp;//复原成原来的样子,以便下一个移动可以使用 
            }
            if (k%3!=0)//可左移的 
            {
                temp=a[k];a[k]=a[k-1];a[k-1]=temp;
                has=get_hash_code(a);
                if (hash[has]==0)
                {
                    strcpy(s[has].str,a);
                    s[has].fx=3;
                    s[has].fa=w;
                    s[has].k=k-1;
                    hash[has]=1;
                    EnQueue(&Q,has);
                }
                temp=a[k];a[k]=a[k-1];a[k-1]=temp;
            }
            if (k%3!=2)//可右移的 
            {
                temp=a[k];a[k]=a[k+1];a[k+1]=temp;
                has=get_hash_code(a);
                if (hash[has]==0)
                {
                    strcpy(s[has].str,a);
                    s[has].fx=4;
                    s[has].fa=w;
                    s[has].k=k+1;
                    hash[has]=1;
                    EnQueue(&Q,has);
                }
                temp=a[k];a[k]=a[k+1];a[k+1]=temp;
            }
            if (k<6)//可下移的 
            {
                temp=a[k];a[k]=a[k+3];a[k+3]=temp;
                has=get_hash_code(a);
                if (hash[has]==0)
                {
                    strcpy(s[has].str,a);
                    s[has].fx=2;
                    s[has].fa=w;
                    s[has].k=k+3;
                    hash[has]=1;
                    EnQueue(&Q,has);
                }temp=a[k];a[k]=a[k+3];a[k+3]=temp;
            }
            
    }
}

int main()
{
    int i,j,m,l;
    bfs();
    while(gets(end)!=NULL)
    { 
    j=0;
    l=strlen(end);
    for(i=0;i<l;i++){
    if(end[i]==' ')continue;
       if(end[i]=='x')
       {
          end[j]='0';
          j++;
       }else end[j++]=end[i];
    }
       end[j]='\0';
    m=get_hash_code(end);
    //printf("%s \n",end);
       if(hash[m])
          print(m);
       else 
         printf("unsolvable\n");
      // system("pause");
      } 
    return 0;
} 
View Code

 

转载于:https://www.cnblogs.com/huzhenbo113/p/3231286.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值