zoukankan      html  css  js  c++  java
  • 着色方案(bzoj 1079)

    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

     100%的数据满足:1 <= k <= 15, 1 <= ci <= 5

    /*
        直接状态压缩是显然是不可行的,我们考虑如果没有相邻颜色不相同的限制的话,
        如果两种油漆能染的木块数目相同,我们就可以认为两种油漆无差别。
        设dp[a1][a2][a3][a4][a5]为能染1个木块的油漆有a1种……的方案数。
        但是有相邻颜色的限制,如果上一次用了颜色数为last的油漆,
        那么这一次有一种颜色数为last-1的油漆就不能用了,转移的时候注意一下。
    */
    #include<iostream>
    #include<cstdio>
    #define mod 1000000007
    #define lon long long
    using namespace std;
    int s[6],dp[16][16][16][16][16][16],k;
    int dfs(int a1,int a2,int a3,int a4,int a5,int last){
        if(dp[a1][a2][a3][a4][a5][last]) return dp[a1][a2][a3][a4][a5][last];
        if(a1+a2+a3+a4+a5==0) return dp[a1][a2][a3][a4][a5][last]=1;
        lon tot=0;
        if(a1) tot+=1LL*(a1-(last==2))*dfs(a1-1,a2,a3,a4,a5,1),tot%=mod;
        if(a2) tot+=1LL*(a2-(last==3))*dfs(a1+1,a2-1,a3,a4,a5,2),tot%=mod;
        if(a3) tot+=1LL*(a3-(last==4))*dfs(a1,a2+1,a3-1,a4,a5,3),tot%=mod;
        if(a4) tot+=1LL*(a4-(last==5))*dfs(a1,a2,a3+1,a4-1,a5,4),tot%=mod;
        if(a5) tot+=1LL*a5*dfs(a1,a2,a3,a4+1,a5-1,5),tot%=mod;
        return dp[a1][a2][a3][a4][a5][last]=tot;
    }
    int main(){
        scanf("%d",&k);
        for(int i=1;i<=k;i++){
            int x;scanf("%d",&x);
            s[x]++;
        }
        printf("%d",dfs(s[1],s[2],s[3],s[4],s[5],0));
        return 0;
    }
  • 相关阅读:
    lintcode491 回文数
    lintcode514 栅栏染色
    lintcode433 岛屿的个数
    lintcode142 O(1)时间检测2的幂次
    lintcode166 链表倒数第n个节点
    lintcode539 移动零
    lintcode: Check Sum of Square Numbers
    lintcode: Missing String
    lintcode 二叉树的锯齿形层次遍历
    Mysql 游标的定义与使用方式
  • 原文地址:https://www.cnblogs.com/harden/p/6759467.html
Copyright © 2011-2022 走看看