• 【双向广搜+逆序数优化】【HDU1043】【八数码】


    HDU上的八数码 数据强的一B


    首先:双向广搜

    先处理正向搜索,再处理反向搜索,直至中途相遇


    visit 和 队列都是独立的。 可以用一个过程来完成这2个操作,减少代码量。(一般还要个深度数组)

    优化效率很强


    逆序数优化

    在忽略空格的情况,会发现 空格无论怎么变,1-8的排列的逆序数始终要为偶数,才能有解(空格无视)

    而且证明得出:如果满足逆序条件,必定有解!

    拓展

    N*N的情况

    N×N的棋盘,N为奇数时,与八数码问题相同。

    N为偶数时,空格每上下移动一次,奇偶性改变。称空格位置所在的到目标空格所在的行步数为空格的距离(不计左右距离),若两个状态的可相互到达,则有,两个状态的逆序奇偶性相同且空格距离为偶数,或者,逆序奇偶性不同且空格距离为奇数数。否则不能。




    >推广到三维N×N×N

    其实,三维的结论和二维的结论是一样的。

    考虑左右移动空格,逆序不变;同一层上下移动空格,跨过N-1个格子;上下层移动空格,跨过N^2-1个格子。

    当N为奇数时,N-1和N^2-1均为偶数,也就是任意移动空格逆序奇偶性不变。那么逆序奇偶性相同的两个状态可相互到达。

    当N为偶数时,N-1和N^2-1均为奇数,也就是令空格位置到目标状态空格位置的y z方向的距离之和,称为空格距离。若空格距离为偶数,两个逆序奇偶性相同的状态可相互到达;若空格距离为奇数,两个逆序奇偶性不同的状态可相互到达。


    代码:
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <queue>
    #define oo 0x13131313
    using namespace std;
    struct node
    {
        int operator[](int index) const {
            return A[index];
        }
        int& operator[](int index) {
            return A[index];
        }
        int A[10];
        int xnum;
        int deep;
        int Contor;
        void JSContor()
        {
            int temp=0,p=1;
            for(int i=8;i>=0;i--)
            {
                int tot=0;
                for(int j=0;j<i;j++)
                    if(A[j]<A[i]) tot++;
                temp+=(A[i]-tot-1)*p;
                p=p*(9-i);
            }
            Contor=temp+1;
        }
    };
    int visit[2][370000];
    int dist[2][370000];
    int DEEP[2][370000];
    int dANS[2][370000];
    char f[4]={'u','d','l','r'};
    queue <node> Q[2];
    node start;
    node End;
    
    char AAA[20];
    void init()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
    }
    void input()
    {
        memset(visit,0,sizeof(visit));
        for(int i=0;i<9;i++)
        {
            if(AAA[i]=='x')
            {
                start[i]=9;
                start.xnum=i;
            }
            else start[i]=AAA[i]-'0';
            End[i]=i+1;
        }
        End.xnum=8;
        End.deep=0;
        start.deep=0;
    }
    void csh()
    {
        while(Q[0].empty()!=1) Q[0].pop();
        start.JSContor();
        visit[0][start.Contor]=1;
        Q[0].push(start);
    
        while(Q[1].empty()!=1) Q[1].pop();
        End.JSContor();
        visit[1][End.Contor]=1;
        Q[1].push(End);
    }
    int GAN(int pos)
    {
            node s,t;
            s=Q[pos].front();
            Q[pos].pop();
            if(visit[pos^1][s.Contor]==1) {
                                             return s.Contor;
                                          }
            s.deep++;
            //
            t=s;
            if(((t.xnum)/3)!=0)
            {
                swap(t[t.xnum],t[t.xnum-3]);
                t.xnum=t.xnum-3;
                t.JSContor();
                if(visit[pos][t.Contor]==0)
                {
                    Q[pos].push(t);
                    visit[pos][t.Contor]=1;
                    dist[pos][t.Contor]=s.Contor;
                    dANS[pos][t.Contor]=0;
                    DEEP[pos][t.Contor]=t.deep;
                }
            }
    
            //
            t=s;
            if(((t.xnum)/3)!=2)
            {
                swap(t[t.xnum],t[t.xnum+3]);
                t.xnum=t.xnum+3;
                t.JSContor();
                if(visit[pos][t.Contor]==0)
                {
                    Q[pos].push(t);
                    visit[pos][t.Contor]=1;
                    dist[pos][t.Contor]=s.Contor;
                    dANS[pos][t.Contor]=1;
                    DEEP[pos][t.Contor]=t.deep;
                }
            }
            //
            t=s;
            if(t.xnum%3!=0)
            {
                swap(t[t.xnum],t[t.xnum-1]);
                t.xnum--;
                t.JSContor();
                if(visit[pos][t.Contor]==0)
                {
                    Q[pos].push(t);
                    visit[pos][t.Contor]=1;
                    dist[pos][t.Contor]=s.Contor;
                    dANS[pos][t.Contor]=2;
                    DEEP[pos][t.Contor]=t.deep;
                }
            }
            //
            t=s;
            if((t.xnum+1)%3!=0)
            {
                swap(t[t.xnum],t[t.xnum+1]);
                t.xnum++;
                t.JSContor();
                if(visit[pos][t.Contor]==0)
                {
                    Q[pos].push(t);
                    visit[pos][t.Contor]=1;
                    dist[pos][t.Contor]=s.Contor;
                    dANS[pos][t.Contor]=3;
                    DEEP[pos][t.Contor]=t.deep;
                }
            }
            return 0;
    }
    void twobfs()
    {
        void print(int ok1);
       csh();
       int ok1=0,ok2=0;
       while(Q[0].empty()!=1&&Q[1].empty()!=1)
       {
           ok1=GAN(0);
           if(ok1!=0) break;
           ok2=GAN(1);
           if(ok2!=0) {ok1=ok2;break;}
        }
         print(ok1);
    }
    char ANS[20];
    void print(int ok1)
    {
            int tot=1;
            for(int p=ok1;p!=start.Contor;p=dist[0][p])
            {
                ANS[tot]=f[dANS[0][p]];
                tot++;
            }
            for(int i=tot-1;i>=1;i--)
            printf("%c",ANS[i]);
            tot=1;
            for(int p=ok1;p!=End.Contor;p=dist[1][p])
            {
                ANS[tot]=f[dANS[1][p]^1];
                tot++;
            }
            for(int i=1;i<tot;i++)
            printf("%c",ANS[i]);
            printf("
    ");
    }
    int OK=1;
    int JZyj()
    {
        int tot1=0;
        for(int i=0;i<=8;i++)
            for(int j=0;j<i;j++)
        {
            if(start[i]!=9&&start[j]!=9)
            if(start[i]<start[j]) tot1++;
        }
        if(tot1%2==0) return 1;
        else return 0;
    }
    int main()
    {
        //init();
        char c;
    	while(scanf("%c  %c  %c  %c  %c  %c  %c  %c  %c
    ",&AAA[0],&AAA[1],&AAA[2],&AAA[3],&AAA[4],&AAA[5],&AAA[6],&AAA[7],&AAA[8])!=EOF)
        {
            input();
            if( JZyj())
            twobfs();
            else printf("unsolvable
    ");
        }
    }
    

    利用预处理稍微压缩一下BFS后(BFS多移动一般都可以用预处理压缩)

    简化了一下BFS后 看起来就是舒服
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <queue>
    #define oo 0x13131313
    using namespace std;
    struct node
    {
        int operator[](int index) const {
            return A[index];
        }
        int& operator[](int index) {
            return A[index];
        }
        int A[10];
        int xnum;
        int deep;
        int Contor;
        void JSContor()
        {
            int temp=0,p=1;
            for(int i=8;i>=0;i--)
            {
                int tot=0;
                for(int j=0;j<i;j++)
                    if(A[j]<A[i]) tot++;
                temp+=(A[i]-tot-1)*p;
                p=p*(9-i);
            }
            Contor=temp+1;
        }
    };
    int visit[2][370000];
    int dist[2][370000];
    int DEEP[2][370000];
    int dANS[2][370000];
    char f[4]={'u','d','l','r'};
    int fx[5]={-1,+1,0,0};
    int fy[5]={0,0,-1,+1};
    queue <node> Q[2];
    node start;
    node End;
    
    char AAA[20];
    void init()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
    }
    void input()
    {
        memset(visit,0,sizeof(visit));
        for(int i=0;i<9;i++)
        {
            if(AAA[i]=='x')
            {
                start[i]=9;
                start.xnum=i;
            }
            else start[i]=AAA[i]-'0';
            End[i]=i+1;
        }
        End.xnum=8;
        End.deep=0;
        start.deep=0;
    }
    void csh()
    {
        while(Q[0].empty()!=1) Q[0].pop();
        start.JSContor();
        visit[0][start.Contor]=1;
        Q[0].push(start);
    
        while(Q[1].empty()!=1) Q[1].pop();
        End.JSContor();
        visit[1][End.Contor]=1;
        Q[1].push(End);
    }
    int GAN(int pos)
    {
            node s,t;
            int x,y,p;
            s=Q[pos].front();
            Q[pos].pop();
            if(visit[pos^1][s.Contor]==1) {
                                             return s.Contor;
                                          }
            s.deep++;
            x=s.xnum/3;y=s.xnum%3;
            for(int i=0;i<=3;i++)
            {
                t=s;
                if(x+fx[i]<=2&&x+fx[i]>=0&&y+fy[i]<=2&&y+fy[i]>=0)
                {
                    p=(x+fx[i])*3+y+fy[i];
                     swap(t[t.xnum],t[p]);
                     t.xnum=p;
                     t.JSContor();
                    if(visit[pos][t.Contor]==0)
                 {
                     Q[pos].push(t);
                     visit[pos][t.Contor]=1;
                     dist[pos][t.Contor]=s.Contor;
                     dANS[pos][t.Contor]=i;
                     DEEP[pos][t.Contor]=t.deep;
                }
                }
            }
            return 0;
    }
    void twobfs()
    {
        void print(int ok1);
       csh();
       int ok1=0,ok2=0;
       while(Q[0].empty()!=1&&Q[1].empty()!=1)
       {
           ok1=GAN(0);
           if(ok1!=0) break;
           ok2=GAN(1);
           if(ok2!=0) {ok1=ok2;break;}
        }
         print(ok1);
    }
    char ANS[20];
    void print(int ok1)
    {
            int tot=1;
            for(int p=ok1;p!=start.Contor;p=dist[0][p])
            {
                ANS[tot]=f[dANS[0][p]];
                tot++;
            }
            for(int i=tot-1;i>=1;i--)
            printf("%c",ANS[i]);
            tot=1;
            for(int p=ok1;p!=End.Contor;p=dist[1][p])
            {
                ANS[tot]=f[dANS[1][p]^1];
                tot++;
            }
            for(int i=1;i<tot;i++)
            printf("%c",ANS[i]);
            printf("
    ");
    }
    int OK=1;
    int JZyj()
    {
        int tot1=0;
        for(int i=0;i<=8;i++)
            for(int j=0;j<i;j++)
        {
            if(start[i]!=9&&start[j]!=9)
            if(start[i]<start[j]) tot1++;
        }
        if(tot1%2==0) return 1;
        else return 0;
    }
    int main()
    {
        //init();
        char c;
    	while(scanf("%c  %c  %c  %c  %c  %c  %c  %c  %c
    ",&AAA[0],&AAA[1],&AAA[2],&AAA[3],&AAA[4],&AAA[5],&AAA[6],&AAA[7],&AAA[8])!=EOF)
        {
            input();
            if( JZyj())
            twobfs();
            else printf("unsolvable
    ");
        }
    }
    



  • 相关阅读:
    结对项目:四则运算
    Word Count(C语言)
    自我介绍+软工5问
    如何在博客园中使用markdown
    如何设计一门语言(九)——类型
    如何设计一门语言(八)——异步编程和CPS变换
    如何设计一门语言(七)——闭包、lambda和interface
    时隔多年我又再一次体验了一把跟大神聊天的感觉
    20199107 2019-2020-2 《网络攻防实践》第4周作业
    20199107 2019-2020-2 《网络攻防实践》第3周作业
  • 原文地址:https://www.cnblogs.com/zy691357966/p/5480373.html
Copyright © 2020-2023  润新知