zoukankan      html  css  js  c++  java
  • [BZOJ]1079 着色方案(SCOI2008)

      相邻色块不同的着色方案,似乎这道题已经见过3个版本了。

    Description

      有n个木块排成一行,从左到右依次编号为1~n。你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块。所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n。相邻两个木块涂相同色显得很难看,所以你希望统计任意两个相邻木块颜色不同的着色方案。

    Input

      第一行为一个正整数k,第二行包含k个整数c1, c2, ... , ck。

    Output

      输出一个整数,即方案总数模1,000,000,007的结果。

    Sample Input

      3
      1 2 3

    Sample Output

      10

    HINT

      1 <= k <= 15,,1 <= ci <= 5。

    Solution

      k和ci都这么小,状压肯定没跑了。

      如果你把k和ci的数据范围换一换,你应该会很容易地设计出状态吧。

      我们先试着从5^15的状态表示法入手,看看有什么可改进的地方。

      你会发现有很多状态本质上是一样的,颜色之间其实是没有区别的。

      例如七种颜色的数量{1,4,3,2,2,1,2}和{1,2,3,2,4,2,1}排序后都是{1,1,2,2,2,3,4}。

      所以我们就试着把状态压一压,状态表示为当前每种数量的颜色有多少种。

      这样就状态又变成15^5啦,科学得不要不要的。

      具体状态为f[i][j][k]表示已经涂了i格,状态为j,最后一格涂的是在当前状态中数量为k的颜色,转移自己看着办吧。

      时间复杂度O(n*k^ci*ci^2),记忆化搜索似乎会省掉那个n?(n=Σci)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define MN 1100005
    #define mod 1000000007
    using namespace std;
    int m,n,S;
    int g[6],ys[6],f[2][MN][6],q[2][MN],tp[2];
    bool u[MN];
    
    inline int read()
    {
        int n=0,f=1; char c=getchar();
        while (c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
        while (c>='0' && c<='9') {n=n*10+c-'0'; c=getchar();}
        return n*f;
    }
    
    inline void rw(int &x,int y) {x+=y; if (x>=mod) x-=mod;}
    
    int main()
    {
        register int x,i,j,k,l,lg,rg,gs;
        for (m=read();m--;) ++g[x=read()],n+=x;
        for (ys[1]=1,i=2;i<=5;++i) ys[i]=ys[i-1]<<4;
        for (i=1;i<=5;++i) S+=g[i]*ys[i];
        for (f[0][q[0][tp[0]=1]=S][0]=1,lg=0,rg=1,i=0;i<n;++i,swap(lg,rg))
        {
            tp[rg]=0;    
            for (j=1;j<=tp[lg];++j) if (!u[q[lg][j]])
                for (u[q[lg][j]]=true,k=0;k<5;f[lg][q[lg][j]][k++]=0) if (f[lg][q[lg][j]][k])
                    for (x=q[lg][j],l=5;l;x%=ys[l--]) if (gs=x/ys[l])
                        if (k!=l)
                            rw(f[rg][q[lg][j]-ys[l]+ys[l-1]][l-1],1LL*f[lg][q[lg][j]][k]*gs%mod),
                            q[rg][++tp[rg]]=q[lg][j]-ys[l]+ys[l-1];
                        else if (gs>1)
                            rw(f[rg][q[lg][j]-ys[l]+ys[l-1]][l-1],1LL*f[lg][q[lg][j]][k]*(gs-1)%mod),
                            q[rg][++tp[rg]]=q[lg][j]-ys[l]+ys[l-1];
            for (j=1;j<=tp[lg];++j) u[q[lg][j]]=false;
        }
        printf("%d",f[lg][0][0]);
    }

    Last Word

      世界上还有比恶意散播题解的更毒的人吗?

  • 相关阅读:
    用wamp配置的环境,想用CMD连接mysql怎么连
    Mysql删除表
    MySQL创建表
    Leetcode 130. Surrounded Regions
    Leetcode 111. Minimum Depth of Binary Tree
    Leetcode 110. Balanced Binary Tree
    Leetcode 98. Validate Binary Search Tree
    Leetcode 99. Recover Binary Search Tree
    Leetcode 108. Convert Sorted Array to Binary Search Tree
    Leetcode 105. Construct Binary Tree from Preorder and Inorder Traversal
  • 原文地址:https://www.cnblogs.com/ACMLCZH/p/7639563.html
Copyright © 2011-2022 走看看