記憶化搜索 [SCOI2008]着色方案

問題 B: [SCOI2008]着色方案
時間限制: 1 Sec 內存限制: 162 MB
提交: 80 解決: 38
[提交][狀態][討論版]
題目描述
有n個木塊排成一行,從左到右依次編號爲1~n。你有k種顏色的油漆,其中第i種顏色的油漆足夠塗ci個木塊。
所有油漆剛好足夠塗滿所有木塊,即c1+c2+…+ck=n。相鄰兩個木塊塗相同色顯得很難看,所以你希望統計任意兩
個相鄰木塊顏色不同的着色方案。

輸入
第一行爲一個正整數k,第二行包含k個整數c1, c2, … , ck。

輸出
輸出一個整數,即方案總數模1,000,000,007的結果。

樣例輸入
3
1 2 3
樣例輸出
10

我們可以發現,可用剩餘次數相同的顏色並沒必要區別它們,直接記錄還有多少種就行了。因此,我們每使用一種顏色,此剩餘使用數量的顏色減一,使用數量減一的顏色種數加一。那麼方案數+=此次數顏色數量×修改之後的方案總數。但考慮顏色不能連續,搜的時候判斷就行了,如果是同一種剩餘次數的顏色,-1就行了。
而且顏色很少?使用次數最大爲5?可以開個6維數組記錄各剩下多少和上一個是什麼就行了。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#define mod 1000000007
#define ll long long
using namespace std;
int k,a[6];ll f[16][16][16][16][16][6];
ll dfs(int a1,int a2,int a3,int a4,int a5,int las)
{
    if((a1|a2|a3|a4|a5)==0)return f[a1][a2][a3][a4][a5][las]=1;
    if(f[a1][a2][a3][a4][a5][las])return f[a1][a2][a3][a4][a5][las];
    ll s=0;
    if(a1)s+=(a1-(las==2))*dfs(a1-1,a2,a3,a4,a5,1),s%=mod;
    if(a2)s+=(a2-(las==3))*dfs(a1+1,a2-1,a3,a4,a5,2),s%=mod;
    if(a3)s+=(a3-(las==4))*dfs(a1,a2+1,a3-1,a4,a5,3),s%=mod;
    if(a4)s+=(a4-(las==5))*dfs(a1,a2,a3+1,a4-1,a5,4),s%=mod;
    if(a5)s+=a5*dfs(a1,a2,a3,a4+1,a5-1,5),s%=mod;
    return f[a1][a2][a3][a4][a5][las]=s;
}
int main()
{
    scanf("%d",&k);int x;
    for(int i=1;i<=k;i++)scanf("%d",&x),a[x]++;
    printf("%lld\n",dfs(a[1],a[2],a[3],a[4],a[5],0));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章