• [BZOJ 1079][SCOI 2008]着色方案


    1079: [SCOI2008]着色方案

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2237  Solved: 1361
    [Submit][Status][Discuss]

    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$ ...

    注意到 $k$ 的范围很小, 所以首先我们可以想到的定义状态的方案是把每种油漆剩余的数量定义进状态, 但是 $15$ 维的记忆化数组怕是是个人都不想写吧...而且$5^{15}approx 3.05 imes 10^{10}$ 并不能开得下...

    但是我们会发现, 其实不同的油漆只要余量相等, 对于答案的影响并没有什么区别, 所以我们可以分别将余量为 $1,2,3,4,5$ 的油漆种数定义进状态, 再加一维表示上次用的是哪种油漆, $DFS$ 处理就好了

    代码挺好写, 但看起来比较恶心...

    参考代码

    GitHub

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 
     7 const int MOD=1e9+7;
     8 const int MAXN=16;
     9 
    10 int n;
    11 int data[MAXN];
    12 int dp[MAXN][MAXN][MAXN][MAXN][MAXN][5];
    13 
    14 int DFS(int,int,int,int,int,int);
    15 
    16 int main(){
    17     scanf("%d",&n);
    18     int tmp;
    19     for(int i=0;i<n;i++){
    20         scanf("%d",&tmp);
    21         data[tmp]++;
    22     }
    23     for(int i=0;i<=5;i++){
    24         dp[0][0][0][0][0][i]=1;
    25     }
    26     printf("%d
    ",DFS(data[1],data[2],data[3],data[4],data[5],0));
    27     return 0;
    28 }
    29 
    30 int DFS(int r1,int r2,int r3,int r4,int r5,int last){
    31     if(dp[r1][r2][r3][r4][r5][last]!=0)
    32         return dp[r1][r2][r3][r4][r5][last];
    33     else{
    34         long long tmp=0;
    35         if(r1>0)
    36             tmp+=1ll*(last==2?r1-1:r1)*DFS(r1-1,r2,r3,r4,r5,1);
    37         if(r2>0)
    38             tmp+=1ll*(last==3?r2-1:r2)*DFS(r1+1,r2-1,r3,r4,r5,2);
    39         if(r3>0)
    40             tmp+=1ll*(last==4?r3-1:r3)*DFS(r1,r2+1,r3-1,r4,r5,3);
    41         if(r4>0)
    42             tmp+=1ll*(last==5?r4-1:r4)*DFS(r1,r2,r3+1,r4-1,r5,4);
    43         if(r5>0)
    44             tmp+=1ll*r5*DFS(r1,r2,r3,r4+1,r5-1,5);
    45         dp[r1][r2][r3][r4][r5][last]=tmp%MOD;
    46         return dp[r1][r2][r3][r4][r5][last];
    47     }
    48 }
    Backup

     

  • 相关阅读:
    外感上吐下泻案
    口唇口腔紅肿案
    柴胡桂枝汤---刘渡舟
    肺结核病人外感咳嗽不止案
    下肢麻木案
    老年人全身皮肤瘙痒案
    眩晕案
    頑固头痛失眠案
    PHP 点阵5*7字体
    PHP workerMan tcp与webSocket 透传互通
  • 原文地址:https://www.cnblogs.com/rvalue/p/7684018.html
Copyright © 2020-2023  润新知