bzoj 1079 [SCOI2008]着色方案
生活随笔
收集整理的這篇文章主要介紹了
bzoj 1079 [SCOI2008]着色方案
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
bzoj 1079 [SCOI2008]著色方案
Description
有n個木塊排成一行,從左到右依次編號為1~n。你有k種顏色的油漆,其中第i種顏色的油漆足夠涂ci個木塊。所有油漆剛好足夠涂滿所有木塊,即c1+c2+...+ck=n。相鄰兩個木塊涂相同色顯得很難看,所以你希望統計任意兩個相鄰木塊顏色不同的著色方案。
Input
第一行為一個正整數k,第二行包含k個整數c1, c2, ... , ck。
Output
輸出一個整數,即方案總數模1,000,000,007的結果。
Sample Input
31 2 3Sample Output
10HINT
100%的數據滿足:1 <= k <= 15, 1 <= ci <= 5
這道題有點玄學,不管了,開始我也沒想到要這么做,講一下大概做法吧.我們設f[a][b][c][d][e][last]為剩余涂色次數為1.2.3...5次的顏色數,last表示上次涂了剩余顏色數為last的顏色,舉個例子,f[1][2][3][4][5][2]表示當前有1個顏色可以涂一次,兩個顏色可以涂兩次...上次涂的顏色是剩余涂色次數為2的顏色中的一個.那么我們可以想到這個狀態可以由f[0][3][4][5][x]轉移過來,那么我們就想到了可以dp了,由于對于剩余涂色次數為x的顏色,它們的性質是一樣的,我們把它們加起來就可以了.于是我們可以打記憶化了.
代碼如下
#include <cstdio> #include <algorithm> using namespace std;typedef long long LL;static const int maxm=15+1; static const int MOD=1e9+7;LL f[maxm][maxm][maxm][maxm][maxm][maxm]; int cnt[maxm]; int n,x;LL dfs(int a,int b,int c,int d,int e,int last){LL ret=0;if(!(a+b+c+d+e))return f[a][b][c][d][e][last]=1;if(f[a][b][c][d][e][last])return f[a][b][c][d][e][last];if(a)ret+=(a-(last==2))*dfs(a-1,b,c,d,e,1),ret%=MOD; //如果上次涂了剩余次數為2的顏色,那么它現在就轉移到1的位置去了,所以要減一if(b)ret+=(b-(last==3))*dfs(a+1,b-1,c,d,e,2),ret%=MOD;if(c)ret+=(c-(last==4))*dfs(a,b+1,c-1,d,e,3),ret%=MOD;if(d)ret+=(d-(last==5))*dfs(a,b,c+1,d-1,e,4),ret%=MOD;if(e)ret+=e*dfs(a,b,c,d+1,e-1,5),ret%=MOD;return f[a][b][c][d][e][last]=ret; }int main(){scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&x),cnt[x]++;printf("%lld\n",dfs(cnt[1],cnt[2],cnt[3],cnt[4],cnt[5],0));return 0; }點我進入AC通道
轉載于:https://www.cnblogs.com/Exbilar/p/6701541.html
總結
以上是生活随笔為你收集整理的bzoj 1079 [SCOI2008]着色方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU 1043 Eight(八数码)
- 下一篇: 服务器强迫患者 ;软件试用狂人