HDU 1067(HASH + BFS)

来源:互联网 发布:php上传图片到本地 编辑:程序博客网 时间:2024/06/05 19:50

题意:如图分部这的卡片,每次移动一个空格,让比空格左边的数大一的数移动到空格。最后达到目标状态。问最少的步数。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<queue>using namespace std;#define MAXN 1000007typedef long long ll;ll Hash[MAXN];struct Node{    int map[4][8],step;    bool operator == (const Node &p) const {        for(int i=0;i<4;i++)            for(int j=0;j<8;j++)                if(map[i][j]!=p.map[i][j])                    return false;        return true;    }    //手写hash    ll HashValue(){        ll value=0;        for(int i=0;i<4;i++)            for(int j=0;j<8;j++)                value+=(value<<ll(1))+(ll)map[i][j];        return value;    }};Node Start,End;void Initaite(){    memset(Hash,-1,sizeof(Hash));    for(int i=0;i<4;i++){        Start.map[i][0]=0;        for(int j=1;j<8;j++){            scanf("%d",&Start.map[i][j]);        }    }    Start.step=0;}//最后的结果void GetEnd(){    for(int i=0;i<4;i++){        End.map[i][7]=0;        for(int j=0;j<7;j++){            End.map[i][j]=(i+1)*10+(j+1);        }    }}//取得value的hash值+hash判重bool HashInsert(ll value){    int v=value%MAXN;    while(Hash[v]!=-1&&Hash[v]!=value){        v+=10;        v%=MAXN;    }    if(Hash[v]==-1){        Hash[v]=value;        return true;    }    return false;}void bfs(){    queue<Node>Q;    Node p,q;    Q.push(Start);    HashInsert(Start.HashValue());    while(!Q.empty()){        p=Q.front();        Q.pop();        for(int i=0;i<4;i++){            for(int j=0;j<8;j++){                if(!p.map[i][j]){                    q=p;                    q.step++;                    int value=p.map[i][j-1]+1;//找比map[i][j-1]大1的数                    if(value==1||value%10==8)continue;//0或者value为7的不能移动                    int x,y,flag=true;                    for(int k=0;k<4&&flag;k++){                        for(int l=1;l<8&&flag;l++){                            if(p.map[k][l]==value){                                x=k,y=l;                                flag=false;                            }                        }                    }                    if(!flag){                        swap(q.map[i][j],q.map[x][y]);                        ll value=q.HashValue();                        //hash判重                        if(HashInsert(value)){                            if(q==End){                                printf("%d\n",q.step);                                return ;                            }                            Q.push(q);                        }                    }                }            }        }    }    puts("-1");}void Solve(){    int k=0;    //将11,21,31,41这四个数移到第0列    for(int i=0;i<4;i++){        for(int j=1;j<8;j++){            if(Start.map[i][j]==(k+1)*10+1){                swap(Start.map[i][j],Start.map[k][0]);                k++,i=0,j=0;            }        }    }    if(Start==End){        puts("0");//前四步不记录总步数        return ;    }    bfs();}int main(){    int _case;    scanf("%d",&_case);    GetEnd();    while(_case--){        Initaite();        Solve();    }    return 0;}


#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <queue>#include <map>#define INF 1E9using namespace std;const char ss[32]={11,12,13,14,15,16,17,0,21,22,23,24,25,26,27,0,31,32,33,34,35,36,37,0,41,42,43,44,45,46,47,0};string aim="";struct node{    int x,y;};char m[4][8];struct state{   node pos[50],blank[4];//pos确定每个数字位置,blank是4个空格位置   string s;//图   int lvl;//步数};string m2s()//把图变成字符串{    string now="";    int i,j;    for(i=0;i<4;i++)     for(j=0;j<8;j++)      now.push_back(m[i][j]);    return now;}int get_hash(string s)//获得hash值{    long long ans=0;    for(int i=0;i<32;i++)        ans=(ans<<1)+s[i];    return ans%999991;}bool vis[1000000];queue<state> q;state now,next;node temp;int bfs(){    memset(vis,0,sizeof(vis));    while(!q.empty())q.pop();    int i,j,t=0,k,o,lvl;    for(i=0;i<4;i++)     for(j=0;j<8;j++)     {         temp.x=i;temp.y=j;         if(m[i][j]==0)now.blank[t++]=temp;         else now.pos[m[i][j]]=temp;     }    now.s=m2s();vis[get_hash(now.s)]=1;    now.lvl=1;    q.push(now);    int Aim=get_hash(aim);    while(!q.empty()&&!vis[Aim])    {        now=q.front();q.pop();        next=now;        next.lvl=now.lvl+1;        for(i=0;i<4;i++)        {            node &b=next.blank[i];            o=8*b.x+b.y-1;            t=next.s[o];            if(t%10==7||t==0)continue;//注意空格旁还是空格的情况            k=t+1;            node &p=next.pos[k];            k=p.x*8+p.y;            o++;            swap(next.s[o],next.s[k]);//移动位置            t=get_hash(next.s);            if(!vis[t])            {                if(t==Aim)return next.lvl-1;                swap(p,b);                q.push(next);                vis[t]=1;                swap(p,b);            }            swap(next.s[o],next.s[k]);//恢复        }    }    return vis[Aim]-1;}int main(){   int T;   for(T=0;T<32;T++)aim.push_back(ss[T]);   scanf("%d",&T);   while(T--)   {       memset(m,0,sizeof(m));       int i,j,t;       for(i=0;i<4;i++)        for(j=1;j<8;j++)        {            scanf("%d",&t);            m[i][j]=(char)t;            if(t%10==1) swap(m[i][j],m[(t/10)-1][0]);        }       printf("%d\n",bfs());   }}

#include <iostream>#include <cstring>#include <cstdio>#include <queue>using namespace std;const int MOD=1000007;struct node{    int map[10][10];    int d;};bool vis[MOD];long long gethash(node &t){    int tmp[70],k=0;    memset(tmp,0,sizeof(tmp));    int i,j;    for(i=0;i<4;i++)    {        for(j=0;j<8;j++)        {            tmp[k++]=t.map[i][j]/10;            tmp[k++]=t.map[i][j]%10;        }    }    long long hash=0;    for(i=0;i<k;i++)    {        hash=hash*7+tmp[i];    }    hash=(hash&0x7fffffff)%MOD;    //hash=hash%MOD;    return hash;}int aim[4][8]={    {11,12,13,14,15,16,17,0},    {21,22,23,24,25,26,27,0},    {31,32,33,34,35,36,37,0},    {41,42,43,44,45,46,47,0}};int getaim(node &t){    int i,j;    for(i=0;i<4;i++)    {        for(j=0;j<8;j++)        {            if(t.map[i][j]!=aim[i][j])                return 0;        }    }    return 1;}int change(node &t,int num){    int i,j;    for(i=0;i<4;i++)    {        for(j=0;j<8;j++)        {            if(t.map[i][j]==num+1)            {                t.map[i][j]=0;                return 1;            }        }    }    return 0;}int bfs(node t){    t.map[0][0]=11;    t.map[1][0]=21;    t.map[2][0]=31;    t.map[3][0]=41;    t.d=0;    memset(vis,0,sizeof(vis));    int hash=gethash(t);    vis[hash]=1;    queue<node> q;    q.push(t);    while(!q.empty())    {        t=q.front();        q.pop();        if(getaim(t))            return t.d;        int i,j;        for(i=0;i<4;i++)        {            for(j=1;j<8;j++)            {                if(t.map[i][j]==0&&t.map[i][j-1]%10!=7&&t.map[i][j-1]!=0)                {                    node cur=t;                    change(cur,cur.map[i][j-1]);                    cur.map[i][j]=cur.map[i][j-1]+1;                    cur.d=cur.d+1;                    hash=gethash(cur);                    if(!vis[hash])                    {                        vis[hash]=1;                        q.push(cur);                    }                }            }        }    }    return -1;}int main(){    int n;    scanf("%d",&n);    while(n--)    {        int i,j;        node t;        memset(t.map,0,sizeof(t.map));        for(i=0;i<4;i++)        {            for(j=1;j<8;j++)            {                scanf("%d",&t.map[i][j]);                if(t.map[i][j]%10==1)                    t.map[i][j]=0;            }        }        int res=bfs(t);        printf("%d\n",res);    }    return 0;}

#include <cstdio>#include <iostream>#include <cstring>#include <queue>#include <algorithm>#include <cstdlib>using namespace std;#define mod 1000007long long tag;long long base[33]={1};struct cq{    int map[4][8];    long long step;    int bx[5];  //记录4个空格    int by[5];};queue<cq>Q;int T;long long hash[1000007];bool flag;long long gethash(int t[][8]){    long long h=0;    for(int i=0;i<4;i++)    for(int j=0;j<8;j++)    h += t[i][j] * base[i*8+j];    if(h==tag)flag=true;    return h;}bool insert(long long value){    long long v = value % mod;    while(hash[v]!=-1 && hash[v]!=value)    {        v= (v+10)%mod;    }    if(hash[v]==-1)    {        hash[v]=value;        return true;    }    return false;}bool work(int t[][8]){    long long sb=gethash(t);    return insert(sb);}int aim[4][8]={    11,12,13,14,15,16,17,0,    21,22,23,24,25,26,27,0,    31,32,33,34,35,36,37,0,    41,42,43,44,45,46,47,0};int bfs(){    cq w,e;    while(!Q.empty())    {        w=Q.front();        Q.pop();            for(int i=1;i<=4;i++)            {                e=w;                int xx=e.bx[i];                int yy=e.by[i];                for(int a=0;a<4;a++)                for(int b=0;b<8;b++)                {                    if(e.map[a][b]==0)continue;                    if(e.map[a][b]!=e.map[xx][yy-1]+1)continue;                        swap(e.map[a][b],e.map[xx][yy]);                        if(work(e.map))                        {                            e.step = w.step + 1;                            e.bx[i]=a;                            e.by[i]=b;                            Q.push(e);                            if(flag)                            return e.step;                        }                }            }    }    return -1;}int main(){    for(int i=1;i<33;i++)    {        base[i]=base[i-1]*2;    }    cq w;    tag = 98430874871LL;   //目标状态    scanf("%d",&T);    while(T--)    {        while(!Q.empty())Q.pop();        flag=false;        int k=1;        memset(hash,-1,sizeof(hash));        //insert(tag);        w.map[0][0]=w.map[1][0]=w.map[2][0]=w.map[3][0]=0;        for(int i=0;i<4;i++)        for(int j=1;j<8;j++)        {            scanf("%d",&w.map[i][j]);            if(w.map[i][j]==11){w.bx[k]=i;w.by[k++]=j;swap(w.map[i][j],w.map[0][0]);}            else if(w.map[i][j]==21){w.bx[k]=i;w.by[k++]=j;swap(w.map[i][j],w.map[1][0]);}            else if(w.map[i][j]==31){w.bx[k]=i;w.by[k++]=j;swap(w.map[i][j],w.map[2][0]);}            else if(w.map[i][j]==41){w.bx[k]=i;w.by[k++]=j;swap(w.map[i][j],w.map[3][0]);}        }        w.step=0;        work(w.map);        Q.push(w);        if(flag)printf("0\n");        else printf("%d\n",bfs());    }    return 0;}/*426 31 13 44 21 24 4217 45 23 25 41 36 1146 34 14 12 37 32 4716 43 27 35 22 33 15*/


 

0 0
原创粉丝点击