• [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

     

  • 相关阅读:
    [Symbian] CAknSettingItemList使用心得(转)
    Symbian自定义控件—如何实现跑马灯效果? [symbian](转)
    Retrieving currently active access point(转)
    关于接入点,cmwap,代理设置,WIFI
    Symbian之IAP(Internet Access Point)(转)
    如何使用已连接的接入点
    Symbian 内嵌SIS自启动(inline sis autostart)(转)
    Socket网络编程学习笔记(转)
    Symbian OS C++程序员编码诀窍系统资源的使用(ROM 和 RAM)(转)
    网络socket编程指南 (转)
  • 原文地址:https://www.cnblogs.com/rvalue/p/7684018.html
Copyright © 2020-2023  润新知