[bzoj1079][SCOI2008]着色方案

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

f[a][b][c][d][e][l]  a-e表示剩余1-5个块的颜色的数量,l表示上一个选的颜色,记忆化搜索。

#include<iostream>
#include<cstdio>
#define mod 1000000007
#define ll long long
#define g f[s1][s2][s3][s4][s5][last]
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 

ll f[16][16][16][16][16][6];
int c[16],K,num[6];

ll dfs(int s1,int s2,int s3,int s4,int s5,int last)
{
    if(g)return g;
    if(s1)g+=(s1-(last==1))*dfs(s1-1,s2,s3,s4,s5,0);
    if(s2)g+=(s2-(last==2))*dfs(s1+1,s2-1,s3,s4,s5,1);
    if(s3)g+=(s3-(last==3))*dfs(s1,s2+1,s3-1,s4,s5,2);
    if(s4)g+=(s4-(last==4))*dfs(s1,s2,s3+1,s4-1,s5,3);
    if(s5)g+=s5*dfs(s1,s2,s3,s4+1,s5-1,4);
    g%=mod;
    return g;
}

int main()
{
    K=read();for(int i=1;i<=K;i++)c[i]=read(),num[c[i]]++;
    for(int i=0;i<5;i++)f[0][0][0][0][0][i]=1;
    cout<<dfs(num[1],num[2],num[3],num[4],num[5],0);
    return 0;
}

 

posted @ 2017-03-15 18:39  FallDream  阅读(196)  评论(0编辑  收藏  举报