• bzoj3336 Uva10572 Black and White


    题目描述:

    数据范围:2<=n,m<=8

    题解:

    很明显需要状压。但是怎么压不知道,压什么不知道。

    然后从条件下手。

    条件1要求黑色在一起白色在一起,记录轮廓线很容易做到。

    条件2要求不能出现$2*2$的同色方格。我们还需要再记录当前位置的左上角。

    所以这道题的轮廓线长这样。

    丑图。

    我们需要确定一个顺序记录哪几块互相联通。由于轮廓线奇特的形状我决定这样标号。

    如果编号相同但是并不互相联通我们可以知道他俩不同颜色。

    为了颜色我们决定记录某个块的颜色,这样可以得到所有颜色。

    于是这道题表中存的就是$1$号颜色+所有状态。

    为了方便调试我用了十进制。

    每次调用时都要解压,处理后压缩放回去。

    由于第一行和第一列找不到长这样的轮廓线,我们可以搜出第一行所有状态,处理第一列时直接枚举黑色/白色。

    接下来就是精彩的特判环节。

    (这一部分针对处于中心部位的一干普通点)

    以填黑色为例。

    如果这里不能填黑:

    1.输入要求白色。

    2.拐角处已经有三个黑块。

    3.要考虑到上图中红块填上后$5$号块就不再与不定颜色相邻,我们不能把$5$号块憋死我们要判断$5$号是否有与之联通的好朋友在轮廓线上。

    类似围棋中的气。

    如果没有而且$5$号是白的,那么就不能填黑!

    等等好像是错的。

    如果红块已经到$(n,m-1)$或者是$(n,m)$,而且轮廓线上其他都是黑的,我们可以放黑色。

    所以这又是个特判。

    4.对于3我们考虑的是上下断开,能否出现左右断开?

    当然可能。

    但是只能在最后一行出现。

    所以统计答案时要填回去看一眼。

    真 恶心。

    深思熟虑后糊上去的代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 15
    #define ll long long
    int T,n,m,k,a[N][N];
    char ch[N][N];
    ll bas[N],ans;
    struct Map
    {
        int hed[1000050],cnt[2];
        struct EG
        {
            int nxt;
            ll to,w;
        }e[2000050][2];
        void ae(int f,ll t,ll w)
        {
            e[++cnt[k]][k].to = t;
            e[cnt[k]][k].nxt = hed[f];
            e[cnt[k]][k].w = w;
            hed[f] = cnt[k];
        }
        void push(ll u,ll w)
        {
            for(int j=hed[u%1000000];j;j=e[j][k].nxt)
                if(e[j][k].to==u)
                {
                    e[j][k].w += w;
                    return ;
                }
            ae(u%1000000,u,w);
        }
        void clear()
        {
            cnt[k] = 0;
            memset(hed,0,sizeof(hed));
        }
    }mp;
    int col[N],grp[N],tmp[N],las[N];
    ll zip()
    {
        ll ret = 0;
        for(int i=1;i<=m+1;i++)ret=10*(ret+grp[i]);
        return ret+col[1];
    }
    void upz(ll u)
    {
        memset(tmp,-1,sizeof(tmp));
        tmp[1]=u%10;u/=10;
        for(int i=m+1;i>=1;i--,u/=10)grp[i]=u%10;
        for(int i=1;i<=m+1;i++)
            if(tmp[grp[i]]==-1)tmp[grp[i]]=tmp[grp[i-1]]^1;
        for(int i=1;i<=m+1;i++)
            col[i]=tmp[grp[i]];
    }
    void shake()//get the express
    {
        memset(tmp,0,sizeof(tmp));
        for(int cnt=0,i=1;i<=m+1;i++)
            if(!tmp[grp[i]])tmp[grp[i]]=++cnt;
        for(int i=1;i<=m+1;i++)grp[i]=tmp[grp[i]];
    }
    bool find_friend(int now,int beg,int ens)
    {
        int cnt = 0;
        for(int i=beg;i<=ens;i++)
            if(grp[i]==now)cnt++;
        return cnt>0;
    }
    bool ck1()
    {
        for(int i=1;i<=m;i++)
            if(col[i]+a[1][i]==1)return 0;
        return 1;
    }
    bool ck2()
    {
        int cnt = 0;
        for(int i=2;i<=m;i++)
            cnt+=(col[i]!=col[i-1]);
        return cnt<=2;
    }
    int ck3(int c)
    {
        if(col[m-1]==col[m]&&col[m]==col[m+1]&&col[m+1]==c)return 0;
        int c0 = col[m],ret=1;
        for(int i=1;i<=m+1;i++)las[i]=grp[i];
        col[m] = c;grp[m] = m+2;
        if(col[m-1]==c)
        {
            int kg = grp[m-1];
            for(int i=1;i<=m+1;i++)if(grp[i]==kg)grp[i]=m+2;
        }
        if(col[m+1]==c)
        {
            int kg = grp[m+1];
            for(int i=1;i<=m+1;i++)if(grp[i]==kg)grp[i]=m+2;
        }
        shake();
        for(int i=1;i<=m+1;i++)if(grp[i]>2)ret = 0;
        for(int i=1;i<=m+1;i++)grp[i] = las[i];
        if(col[m-1]==c)
        {
            int kg = grp[m-1];
            for(int i=1;i<=m+1;i++)if(grp[i]==kg)grp[i]=m+2;
        }
        if(col[m+1]==c)
        {
            int kg = grp[m+1];
            for(int i=1;i<=m+1;i++)if(grp[i]==kg)grp[i]=m+2;
        }
        shake();
        for(int i=1;i<=m+1;i++)if(grp[i]>2)ret = 0;
        for(int i=1;i<=m+1;i++)grp[i]=las[i];
        col[m] = c0;
        return ret;
    }
    void PushF()
    {
        for(int i=0;i<(1<<m);i++)
        {
            for(int j=1;j<=m;j++)col[j]=(i>>(j-1))&1;
            if(!ck1())continue;
            if(!ck2())continue;
            grp[1]=1;
            for(int j=2;j<=m+1;j++)if(col[j]==col[j-1])grp[j]=grp[j-1];else grp[j]=grp[j-1]+1;
            mp.push(zip(),1);
        }
    }
    bool check_b(int i,int j)
    {
        if(a[i][j]==0)return 0;
        if(col[j-1]==1&&col[j]==1&&col[j+1]==1)return 0;
        if((i!=n||j!=m)&&(i!=n||j!=m-1))
            if(col[j+1]==0&&!find_friend(grp[j+1],j+2,m+1)&&!find_friend(grp[j+1],1,j-1))
                return 0;
        return 1;
    }
    bool check_w(int i,int j)
    {
        if(a[i][j]==1)return 0;
        if(col[j-1]==0&&col[j]==0&&col[j+1]==0)return 0;
        if((i!=n||j!=m)&&(i!=n||j!=m-1))
            if(col[j+1]==1&&!find_friend(grp[j+1],j+2,m+1)&&!find_friend(grp[j+1],1,j-1))
                return 0;
        return 1;
    }
    int main()
    {
    //    freopen("tt.in","r",stdin);
        scanf("%d",&T);
        bas[0]=1;
        for(int i=1;i<=10;i++)bas[i] = 10*bas[i-1];
        while(T--)
        {
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
            {
                scanf("%s",ch[i]+1);
                for(int j=1;j<=m;j++)
                {
                    if(ch[i][j]=='o')a[i][j]=0;
                    else if(ch[i][j]=='#')a[i][j]=1;
                    else a[i][j]=2;
                }
            }
            ans=0,k=0,mp.clear();
            PushF();
            for(int i=2;i<=n;i++)
            {
                k^=1;mp.clear();
                for(int j=1;j<=mp.cnt[!k];j++)
                {
                    ll now = mp.e[j][!k].to,val = mp.e[j][!k].w;
                    upz(now);
                    for(int o=m+1;o>=2;o--)grp[o]=grp[o-1],col[o]=col[o-1];
                    for(int q=1;q<=m+1;q++)las[q]=grp[q];
                    if(a[i][1]!=0)//black
                    {
                        if(col[2]==1)
                        {
                            col[1]=1,grp[1]=grp[2];
                            shake();
                            mp.push(zip(),val);
                        }else
                        {
                            if(find_friend(grp[2],3,m+1))
                            {
                                col[1]=1,grp[1]=m+2;
                                shake();
                                mp.push(zip(),val);
                            }else if(i==n&&m==2)
                            {
                                col[1]=1,grp[1]=m+2;
                                shake();
                                mp.push(zip(),val);
                            }
                        }
                    }
                    for(int q=1;q<=m+1;q++)grp[q]=las[q];
                    if(a[i][1]!=1)//white
                    {
                        if(col[2]==0)
                        {
                            col[1]=0,grp[1]=grp[2];
                            shake();
                            mp.push(zip(),val);
                        }else
                        {
                            if(find_friend(grp[2],3,m+1))
                            {
                                col[1]=0,grp[1]=m+2;
                                shake();
                                mp.push(zip(),val);
                            }else if(i==n&&m==2)
                            {
                                col[1]=0,grp[1]=m+2;
                                shake();
                                mp.push(zip(),val);
                            }
                        }
                    }
                }
                for(int j=2;j<=m;j++)
                {
                    k^=1,mp.clear();
                    for(int o=1;o<=mp.cnt[!k];o++)
                    {
                        ll now = mp.e[o][!k].to,val = mp.e[o][!k].w;
                        upz(now);int c0 = col[j];
                        if(i==n&&j==m)
                        {
                            if(n==2&&m==2)
                            {
                                if(col[1]==col[3])
                                {
                                    if((a[n][m]==2||a[n][m]!=col[1])&&col[2]==col[1])
                                        ans+=val*ck3(col[1]^1);
                                    else if((a[n][m]==2||a[n][m]==col[1])&&col[2]!=col[1])
                                        ans+=val*ck3(col[1]);
                                }else
                                {
                                    if(a[n][m]==2)ans+=val*(ck3(0)+ck3(1));
                                    else ans+=val*ck3(a[n][m]);
                                }
                            }else
                            {
                                if(col[m-1]==col[m+1])
                                {
                                    if(a[n][m]==2||a[n][m]==col[m-1])
                                        ans+=val*ck3(col[m-1]);
                                }else
                                {
                                    if(a[n][m]==2)ans+=val*(ck3(0)+ck3(1));
                                    else ans+=val*ck3(a[n][m]);
                                }
                            }
                            continue;
                        }
                        if(check_b(i,j))//black
                        {
                            col[j]=1;grp[j]=m+2;
                            for(int q=1;q<=m+1;q++)las[q]=grp[q];
                            if(col[j-1]==1)
                            {
                                int kg = grp[j-1];
                                for(int q=1;q<=m+1;q++)if(grp[q]==kg)grp[q]=m+2;
                            }
                            if(col[j+1]==1)
                            {
                                int kg = grp[j+1];
                                for(int q=1;q<=m+1;q++)if(grp[q]==kg)grp[q]=m+2;
                            }
                            shake();
                            if(i==n&&j==m)ans+=val;
                            mp.push(zip(),val);
                            for(int q=1;q<=m+1;q++)grp[q]=las[q];
                        }
                        col[j] = c0;
                        if(check_w(i,j))//white
                        {
                            col[j]=0;grp[j]=m+2;
                            if(col[j-1]==0)
                            {
                                int kg = grp[j-1];
                                for(int q=1;q<=m+1;q++)if(grp[q]==kg)grp[q]=m+2;
                            }
                            if(col[j+1]==0)
                            {
                                int kg = grp[j+1];
                                for(int q=1;q<=m+1;q++)if(grp[q]==kg)grp[q]=m+2;
                            }
                            shake();
                            if(i==n&&j==m)ans+=val;
                            mp.push(zip(),val);
                        }
                    }
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    NABC的特点分析
    梦断代码读后感(三)
    大道至简-“(我) 能不能学会写程序”
    课堂练习-找水王续
    找1
    课堂练习-找水王
    课堂练习-电梯调度
    课堂练习——计算法能够计算出读者购买一批书的最低价格。
    团队项目—二手书店特色
    梦断代码阅读笔记三
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10233772.html
Copyright © 2020-2023  润新知