著色方案 狀壓dp

2021-09-26 01:25:12 字數 1529 閱讀 2100

題意:

有n個木塊排成一行,從左到右依次編號為1~n。你有k種顏色的油漆,其中第i種顏色的油漆足夠塗ci個木塊。所有油漆剛好足夠塗滿所有木塊,即c1+c2+…+ck=n。相鄰兩個木塊塗相同色顯得很難看,所以你希望統計任意兩個相鄰木塊顏色不同的著色方案。

第一行為乙個正整數k,第二行包含k個整數c1, c2, … , ck。

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

1 <= k <= 15, 1 <= ci <= 5

思路:(**學長部落格[scoi2008]著色方案 (狀態壓縮))

5. 首先,這顯然是一道dp題目,然後開始考慮dp狀態的設定。

6. 對於每個位置的選擇,我們需要知道:一,到當前位置時顏色的剩餘狀態。二,前乙個位置塗得顏色。

7. 顏色的剩餘狀態假如強行記錄的話,共有15種顏色,每種顏色有5次填塗,狀態數總共是5^15。

8. 我們發現,並不一定確切的知道每一種顏色的剩餘狀態,可以通過將顏色歸類,來減少狀態數,這裡需要保證的是同類顏色的處理和對答案的影響完全一致。

9. 可以通過顏色的剩餘填塗次數,將所有顏色分為5類,分別對應剩餘1次、2次、3次、4次、5次。每一類的容量最大為15,狀態數為15^5。

ysx大佬的部落格對**解釋的很好了 —> 著色方案(狀壓dp)

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define inf 0x3f3f3f3f3f3f3f3f

using

namespace std;

typedef

long

long ll;

const

int n =

2e5+10;

const ll mod =

1e9+7;

int vis[n]

;ll dp[16]

[16][

16][16

][16]

[6];

ll dfs

(int a,

int b,

int c,

int d,

int e,

int pre)

if(b >0)

if(c >0)

if(d >0)

if(e >0)

return dp[a]

[b][c]

[d][e]

[pre]

= ans%mod;

}int

main()

cout <<

dfs(vis[1]

, vis[2]

, vis[3]

, vis[4]

, vis[5]

,0);

return0;

}

狀壓dp 玉公尺田 狀壓dp

相關 強相關 327.玉公尺田 狀壓dp 小國王 狀壓dp 是井字形,本題是十字形。思路 狀態計算 時間複雜度 n 2 n 2n o n 22n 12 2 24n 2 n 2 n o n2 12 2 n 2n 2 n o n22n 12 224 看著妥妥超時,但是裡面合法狀態很少 依舊可以過 在此,...

狀壓dp小記

鋪磚 題意 現有nm的一塊地板,需要用12的磚塊去鋪滿,中間不能留有空隙。問這樣方案有多少種 include using namespace std typedef long long ll const int maxn 1 11 int n,m,state ll dp 15 maxn s1表示本行...

狀壓dp學習

p2704 炮兵陣地 1038 裁玻璃 狀壓dp是一種非常暴力的做法,列舉所有可能的狀態,找到要求的最佳狀態,與一般dp不同,前一項與後一項有一些複雜的狀態關係。dp的引數 物品個數 行數等 當前狀態 上乙個狀態 將abc的有無表示成乙個8個狀態,列舉所有組,列舉上乙個狀態,得到當前狀態的最優解 i...