HDU 3095 哈希+双向搜索

        
        
题意:
求从给出的状态到达目标状态需要多少步,无法到达或大于20输出No solution!
解题思路:
哈希+双向搜索,好长呦。
代码:
<pre name="code" class="cpp">#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<utility>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<iterator>
#include<stack>
using namespace std;
const int INF=1e9+7;
const double eps=1e-7;
const int mod=1000007;
const int maxn=5000000;
int f[2],r[2];   
int dx[]={-1,0,1,0},dy[]={0,-1,0,1};
int qq;
bool in(int x,int y){ return x>=0&&x<5&&y>=0&&y<5; }
struct node
{
    int px[2],py[2];  
    int A[5][5];
}nod[2][maxn];  
int B[5][5]={   
    -1,-1,0,-1,-1,
    -1,1,2,3,-1,
    4,5,6,7,8,
    -1,9,10,11,-1,
    -1,-1,0,-1,-1
};
bool Same(int A[][5]) 
{
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
        if(A[i][j]!=B[i][j]) return false;
    return true;
}
int F[20];  //??2^i
void GetF()
{
    F[0]=1;
    for(int i=1;i<15;i++) F[i]=F[i-1]*2;
}
int Get(int A[][5]) 
{
    int ret=0,k=0;
   for(int i=0;i<5;i++)
       for(int j=0;j<5;j++) if(A[i][j]>0) ret+=F[k++]*A[i][j];
    return ret;
}
struct Hash
{
    int v,next,nid,k;   
}ha[mod+maxn];
int hash_id;
bool check(int a,int k1,int b,int k2)  
{
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
        if(nod[k1][a].A[i][j]!=nod[k2][b].A[i][j]) return false;
    return true;
}
int Insert_Hash(int v,int nid,int k) 
{
    int a=v%mod;
    int p=ha[a].next;
    while(p!=-1)
    {
        if(check(ha[p].nid , ha[p].k , nid , k))
                return ha[p].k;
        p=ha[p].next;
    }
    p=++hash_id;
    ha[p].v=v; ha[p].nid=nid; ha[p].k=k;
    ha[p].next=ha[a].next; ha[a].next=p;
    return -1;  
}
bool AddNode(node t,int i,int j,int k)
{
    int x=t.px[i],y=t.py[i];
    int nx=x+dx[j],ny=y+dy[j];
    if(!in(nx,ny)||t.A[nx][ny]<=0) return false;
    node& tt=nod[k][r[k]];
    tt=t;
    swap(tt.A[x][y],tt.A[nx][ny]); 
    tt.px[i]=nx; tt.py[i]=ny;
    int a=Insert_Hash(Get(tt.A),r[k],k);
    if(a==-1){ r[k]++; return false; } 
    else if(a==k) return false;   
    else return true;    
}
void Print(node& t)
{
    for(int i=0;i<5;i++)
    {
        for(int j=0;j<5;j++) printf("%d ",t.A[i][j]);
        puts("");
    }
    puts("=========");
    getchar();
}
bool bfs(int k)
{
    int& be=f[k];
    int en=r[k];
    while(be<en)
    {
        node t=nod[k][be++];
        for(int i=0;i<2;i++)
            for(int j=0;j<4;j++) if(AddNode(t,i,j,k)) return true;
    }
    return false;
}
int solve()
{
    if(Same(nod[0][0].A)) return 0;
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++) nod[1][0].A[i][j]=B[i][j]; 
    nod[1][0].px[0]=0; nod[1][0].py[0]=2;
    nod[1][0].px[1]=4; nod[1][0].py[1]=2;
    int step=0;
    f[0]=f[1]=0,r[0]=r[1]=1;
    for(int i=0;i<mod;i++) ha[i].next=-1;
    hash_id=mod;
    while(f[0]<r[0]||f[1]<r[1]) 
    {
        step++;
        if(bfs(0)) return step;
        step++;
        if(bfs(1)) return step;
        if(step>=20)
                {
                       // cout<<step<<endl;
                        return -1;
                }
    }

    return -1;
}
int main()
{
    int T;
    GetF();
    scanf("%d",&T);
    while(T--)
    {
        qq=20;
        int k=0;
        for(int i=0;i<5;i++)
            for(int j=0;j<5;j++)
        {
            if(B[i][j]==-1) { nod[0][0].A[i][j]=-1; continue; }
            scanf("%d",&nod[0][0].A[i][j]);
            if(nod[0][0].A[i][j]==0)
                { nod[0][0].px[k]=i; nod[0][0].py[k++]=j; }
        }
        int ans=solve();
        if(ans==-1) printf("No solution!\n");
        else printf("%d\n",ans);
    }
    return 0;
}


 
     
 
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值