bzoj 1079 着色方案

題目:
有n個木塊排成一行,從左到右依次編號爲1~n。你有k種顏色的油漆,其
中第i 種顏色的油漆足夠塗ci 個木塊。所有油漆剛好足夠塗滿所有木塊,即c1+c2+…+ck=n。相鄰兩個木塊塗相同色顯得很難看,所以你希望統計任意兩個相鄰木塊顏色不同的着色方案。
輸入輸出格式
輸入格式:
第一行爲一個正整數k,第二行包含k個整數c1, c2, … , ck。
輸出格式:
輸出一個整數,即方案總數模1,000,000,007的結果。
輸入輸出樣例
輸入樣例#1:
3
1 2 3
輸出樣例#1:
10
輸入樣例#2:
5
2 2 2 2 2
輸出樣例#2:
39480
輸入樣例#3:
10
1 1 2 2 3 3 4 4 5 5
輸出樣例#3:
85937576
說明
50%的數據滿足:1 <= k <= 5, 1 <= ci <= 3
100%的數據滿足:1 <= k <= 15, 1 <= ci <= 5
方法:剛開始想着狀壓來着,再想一想,5^15的複雜度=30517578125,蛤蛤蛤,然後換種定義方式,即[15][15][15][15][15][5]的定義方式,表示剩了一塊木板,兩塊木板,三塊木板,四塊木板,五塊木板沒塗的顏色有多少種,再加一維表示相鄰的情況.
dp方程看代碼吧
代碼

#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <algorithm>
#define ll long long
#define mod 1000000007
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
int f[16][16][16][16][16][6],n,a[15];
bool vis[16][16][16][16][16][6];
ll dfs(int a,int b,int c,int d,int e,int x)
{
    ll t=0;
    if (vis[a][b][c][d][e][x]) return f[a][b][c][d][e][x];
    if(a+b+c+d+e==0)return 1;
    if(a) t+=(a-(x==2))*dfs(a-1,b,c,d,e,1);
    if(b) t+=(b-(x==3))*dfs(a+1,b-1,c,d,e,2);
    if(c) t+=(c-(x==4))*dfs(a,b+1,c-1,d,e,3);
    if(d) t+=(d-(x==5))*dfs(a,b,c+1,d-1,e,4);
    if(e) t+=(e)*dfs(a,b,c,d+1,e-1,5);
    vis[a][b][c][d][e][x]=1;
    return f[a][b][c][d][e][x]=(t%mod);
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        a[x]++;
    }
    printf("%lld\n",dfs(a[1],a[2],a[3],a[4],a[5],0)%mod);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章