zoukankan      html  css  js  c++  java
  • BZOJ1079 [SCOI2008]着色方案 动态规划

    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ1079


    题目概括

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


    题解

      一开始想状压dp,压每种颜色的剩余数。

      发现要超时。

      访问了hzwer大佬的博客,立刻恍然大悟。

      我们可以压每种剩余数的颜色个数!

      具体:

      dp[a][b][c][d][e][t]表示剩余1的颜色有a个,剩余2的颜色有b个,剩余3的颜色有c个,剩余4的颜色有d个,剩余5的颜色有e个,之前选择的那种颜色现在还剩t的方案总数。

      那么复杂度为165×6≈6500000,应该不会超时了。

      记忆化dfs比较好写,所以写了记忆化dfs。


    代码

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    const LL mod=1000000007;
    int k,tot[6];
    LL dp[16][16][16][16][16][6];
    LL DP(int a,int b,int c,int d,int e,int t){
        if (dp[a][b][c][d][e][t]!=-1)
            return dp[a][b][c][d][e][t];
        if (a+b+c+d+e==0)
            return dp[a][b][c][d][e][t]=1;
        int A=a-(t==1),B=b-(t==2),C=c-(t==3),D=d-(t==4),E=e;
        LL &res=dp[a][b][c][d][e][t];
        res=0;
        if (a)
            res+=A*DP(a-1,b,c,d,e,0);
        if (b)
            res+=B*DP(a+1,b-1,c,d,e,1);
        if (c)
            res+=C*DP(a,b+1,c-1,d,e,2);
        if (d)
            res+=D*DP(a,b,c+1,d-1,e,3);
        if (e)
            res+=E*DP(a,b,c,d+1,e-1,4);
        return res%=mod;
    }
    int main(){
        memset(dp,-1,sizeof dp);
        memset(tot,0,sizeof tot);
        scanf("%d",&k);
        for (int i=1,a;i<=k;i++){
            scanf("%d",&a);
            tot[a]++;
        }
        printf("%lld",DP(tot[1],tot[2],tot[3],tot[4],tot[5],0));
        return 0;
    }
  • 相关阅读:
    2007上半年网络游戏企业报告总结
    2007中国网络游戏调查报告
    3G门户网总裁张向东:怎分享3G大蛋糕
    网络在线游戏开发心得(服务器端、Java)
    Apache服务器SSL配置
    详解 Windows下apache 实现 SSL
    10个既绚又实用的JQuery特效教程
    Zend Studio 快捷键
    jQuery最佳实践
    2月份13个jQuery最佳插件推荐
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1079.html
Copyright © 2011-2022 走看看