• 【USACO 3.2】Magic Squares


    题意

    4*2个格子分别为
    1234
    8765
    的魔板有3种操作,A:上下两排互换,B:最后一列放到第一列前面,C:中间四个顺时针旋转1格。
    现在给出目标状态,找出最少步数可从原始状态到达目标状态,且输出最小字典序的操作序列。

    题解

    bfs,全排列编码判重可以用康托展开,也可以用vis[8][8][8][8][8][8][8]来判重,因为第八位是固定的,所以要开(8^7)的空间。

    代码

    /*
    USER:19flipp1
    TASK:msquare
    LANG:C++
    */
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define ll long long
    #define in(s) freopen(#s".in","r",stdin);freopen(#s".out","w",stdout);
    #define N 10
    using namespace std;
    int a[N],fac[N];
    struct node{
        int a[N];
        int d;
        char s[25];
    }nd;
    bool vis[320000];
    int cantor(int a[N]){
        int ans=0,c;
        for(int i=1;i<8;i++){
            c=0;
            for(int j=i;j<=8;j++)if(a[i]>a[j])c++;
            ans+=fac[8-i]*c;
        }
        return ans;
    }
    void work(int a[],int i){
        if(i==0){
            for(int j=1;j<=4;j++)swap(a[j],a[9-j]);
        }else if(i==1){
            int t=a[1];
            a[1]=a[4],a[4]=a[3],a[3]=a[2],a[2]=t;
            t=a[5];
            a[5]=a[6],a[6]=a[7],a[7]=a[8],a[8]=t;
        }else if(i==2){
            int t=a[2];
            a[2]=a[7];a[7]=a[6];a[6]=a[3];a[3]=t;
        }
    }
    void bfs(){
        queue<node> q;
        node p;
        for(int i=1;i<=8;i++)p.a[i]=i;
        p.d=0;
        q.push(p);
        while(!q.empty()){
            node p=q.front();
            q.pop();
            int ok=1;
            for(int i=1;i<=8;i++)if(p.a[i]!=nd.a[i]){ok=0;break;}
            if(ok){
                printf("%d
    ",p.d);
                for(int i=1;i<=p.d;i++)
                    printf("%c",p.s[i]);
                puts("");
                break;
            }
            for(int i=0;i<3;i++){
                node np=p;
                work(np.a,i);
                int num=cantor(np.a);
                if(!vis[num]){
                    vis[num]=1;
                    np.d++;
                    np.s[np.d]='A'+i;
                    q.push(np);
                }
            }
        }
    }
    int main(){
        in(msquare);
        fac[0]=1;
        for(int i=1;i<=8;i++){
            scanf("%d",&nd.a[i]);
            fac[i]=fac[i-1]*i;
        }
        bfs();
        return 0;
    }
    

    代码2

    /*
    USER:19flipp1
    TASK:msquare
    LANG:C++
    */
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define ll long long
    #define in(s) freopen(#s".in","r",stdin);freopen(#s".out","w",stdout);
    #define N 10
    using namespace std;
    int a[N],fac[N];
    struct node{
        int a[N];
        int d;
        char s[25];
    }nd;
    bool vis[8][8][8][8][8][8][8];
    void work(int a[],int i){
        if(i==0){
            for(int j=1;j<=4;j++)swap(a[j],a[9-j]);
        }else if(i==1){
            int t=a[1];
            a[1]=a[4],a[4]=a[3],a[3]=a[2],a[2]=t;
            t=a[5];
            a[5]=a[6],a[6]=a[7],a[7]=a[8],a[8]=t;
        }else if(i==2){
            int t=a[2];
            a[2]=a[7];a[7]=a[6];a[6]=a[3];a[3]=t;
        }
    }
    bool Vis(int a[]){
        bool &t=vis[a[1]-1][a[2]-1][a[3]-1][a[4]-1][a[5]-1][a[6]-1][a[7]-1];
        if(t)return 1;
        t=1;
        return 0;
    }
    void bfs(){
        queue<node> q;
        node p;
        for(int i=1;i<=8;i++)p.a[i]=i;
        p.d=0;
        q.push(p);
        while(!q.empty()){
            node p=q.front();
            q.pop();
            int ok=1;
            for(int i=1;i<=8;i++)if(p.a[i]!=nd.a[i]){ok=0;break;}
            if(ok){
                printf("%d
    ",p.d);
                for(int i=1;i<=p.d;i++)
                    printf("%c",p.s[i]);
                puts("");
                break;
            }
            for(int i=0;i<3;i++){
                node np=p;
                work(np.a,i);
                if(!Vis(np.a)){
                    np.d++;
                    np.s[np.d]='A'+i;
                    q.push(np);
                }
            }
        }
    }
    int main(){
        in(msquare);
        fac[0]=1;
        for(int i=1;i<=8;i++){
            scanf("%d",&nd.a[i]);
            fac[i]=fac[i-1]*i;
        }
        bfs();
        return 0;
    }
    
  • 相关阅读:
    用Telnet发送HTTP请求
    chrome失去响应问题
    windows应用技巧
    转载:Linux 的系统服务及其配置(略有修改)
    poj2249 排列组合
    poj1068 模拟
    并查集———吉林省赛(六)G题
    著名医生的药方(深搜)
    源代码(C#)
    (课程设计)简单总结
  • 原文地址:https://www.cnblogs.com/flipped/p/6119178.html
Copyright © 2020-2023  润新知