• 1085. 【GDOI2008】彩球游戏


    Description

    Sarah 最近迷上了一个彩球游戏,游戏在一个 \(N \times M\) 方格上分布有红、蓝、绿三种彥色 的彩球,游戏者每次可以选中一个彩球,进行两种操作:

    操作 1:把以选中的球为右下角的四个相邻小球进行顺时针旋转。

    操作 2:把以选中的球为右下角的四个相邻小球进行颜色替换,替换规则如下:红色变蓝色,蓝色变绿色,绿色变红色。

    注意:每次操作都必须且仅能使用四个小球。

    这个游戏的目标是从给出的初始状态出发, 用最少的操作达到目标状态。

    Solution

    颜色只有 3 种,并且 \(n\times m\) 也不大,可以考虑 3 进制建图。

    建完图后,以起始状态用 \(\mathrm{BFS}\) 拓展,知道结束状态。

    其中旋转和替换都可以通过数学计算来做到 \(\mathcal O(1)\)

    复杂度 \(\mathcal O(3^{n\times m}nm)\),过不去。

    注意到起始状态和目标状态都可以给出,考虑双向搜索。

    从起始状态和目标状态一起搜,搜到一个被另一个搜过的点就可以结束了。

    注意从目标状态搜索的时候操作要反过来。

    Code

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #define N 10
    #define inf 2147483647
    using namespace std;
    int n,m,st,en,all=1,dis,san[20],a[20],id[N][N],bz[44000000];
    short ans[44000000];
    char ch[N];
    int rotate(int sum,int x,int y,int typ)
    {
        int res=(sum/san[id[x][y]+1])*san[id[x][y]+1],x1,x2,x3,x4;
        sum-=res;
        x1=sum/san[id[x][y]];
        sum%=san[id[x][y]];
        x2=sum/san[id[x][y-1]];
        sum%=san[id[x][y-1]];
        res+=(sum/san[id[x-1][y]+1])*san[id[x-1][y]+1];
        sum%=san[id[x-1][y]+1];
        x3=sum/san[id[x-1][y]];
        sum%=san[id[x-1][y]];
        x4=sum/san[id[x-1][y-1]];
        sum%=san[id[x-1][y-1]];
        res+=sum;
        if (typ==1)
        {
            res+=x1*san[id[x][y-1]];
            res+=x2*san[id[x-1][y-1]];
            res+=x3*san[id[x][y]];
            res+=x4*san[id[x-1][y]];
        }
        else
        {
            res+=x1*san[id[x-1][y]];
            res+=x2*san[id[x][y]];
            res+=x3*san[id[x-1][y-1]];
            res+=x4*san[id[x][y-1]];
        }
        return res;
    }
    int change(int sum,int x,int y,int typ)
    {
        int tp=1;
        if (typ==2) tp=-1;
        int res=(sum/san[id[x][y]+1])*san[id[x][y]+1],x1,x2,x3,x4;
        sum-=res;
        x1=sum/san[id[x][y]];
        sum%=san[id[x][y]];
        x1=(x1+tp+3)%3;res+=x1*san[id[x][y]];
        x2=sum/san[id[x][y-1]];
        sum%=san[id[x][y-1]];
        x2=(x2+tp+3)%3;res+=x2*san[id[x][y-1]];
        res+=(sum/san[id[x-1][y]+1])*san[id[x-1][y]+1];
        sum%=san[id[x-1][y]+1];
        x3=sum/san[id[x-1][y]];
        sum%=san[id[x-1][y]];
        x3=(x3+tp+3)%3;res+=x3*san[id[x-1][y]];
        x4=sum/san[id[x-1][y-1]];
        sum%=san[id[x-1][y-1]];
        x4=(x4+tp+3)%3;res+=x4*san[id[x-1][y-1]];
        res+=sum;
        return res;
    }
    int main()
    {
        san[0]=1;
        for (int i=1;i<=16;++i)
            san[i]=san[i-1]*3;
        while (true)
        {
            scanf("%d",&n);
            if (n==0) break;
            scanf("%d",&m);
            st=en=0;
            memset(ans,-1,sizeof(ans));
            memset(bz,0,sizeof(bz));
            for (int i=1;i<=n;++i)
            {
                scanf("%s",ch+1);
                for (int j=1;j<=m;++j)
                {
                    int x=0;
                    id[i][j]=(i-1)*m+(j-1);
                    if (ch[j]=='R') x=0;
                    if (ch[j]=='B') x=1;
                    if (ch[j]=='G') x=2;
                    st+=san[(i-1)*m+(j-1)]*x;
                }
            }
            for (int i=1;i<=n;++i)
            {
                scanf("%s",ch+1);
                for (int j=1;j<=m;++j)
                {
                    int x=0;
                    if (ch[j]=='R') x=0;
                    if (ch[j]=='B') x=1;
                    if (ch[j]=='G') x=2;
                    en+=san[(i-1)*m+(j-1)]*x;
                }
            }
            queue<int> q;
            q.push(st);
            q.push(en);
            ans[st]=0;
            ans[en]=0;
            bz[st]=1;bz[en]=2;
            dis=-1;
            while (!q.empty())
            {
                int x=q.front();q.pop();
                if (dis!=-1) break;
                for (int i=2;i<=n;++i)
                    for (int j=2;j<=m;++j)
                    {
                        int y=rotate(x,i,j,bz[x]);
                        if (bz[y]!=bz[x]&&bz[y]!=0) dis=ans[y]+ans[x]+1;
                        if (ans[y]==-1)
                        {
                            ans[y]=ans[x]+1;
                            bz[y]=bz[x];
                            q.push(y);
                        }
                        y=change(x,i,j,bz[x]);
                        if (bz[y]!=bz[x]&&bz[y]!=0) dis=ans[y]+ans[x]+1;
                        if (ans[y]==-1)
                        {
                            ans[y]=ans[x]+1;
                            bz[y]=bz[x];
                            q.push(y);
                        }
                    }
            }
            printf("%d\n",dis);
        }
        return 0;
    }
    
  • 相关阅读:
    JVM01---简介
    SpringBoot-01创建项目,实例
    git的三种提交方式(目前两种)
    Spring-事务
    JDK及CGLIB动态代理-AOP4种增强
    Spring-静态代理
    Spring-Aop
    初识jvm-1.Java类的加载机制
    java公开课-06-实用类
    java公开课-05-集合及Socket网络编程(简介)
  • 原文地址:https://www.cnblogs.com/Livingston/p/15831570.html
Copyright © 2020-2023  润新知