題意:
有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...