狀壓DP的總結

2022-05-01 20:36:08 字數 1742 閱讀 5665

狀壓dp的標誌

①資料小 ②通過題目所給出的條件以後得到的特徵集合小

一:cf259div2 d:

題目大意:保證b[i]中每個數互質,給出a[i],然後求1~n的abs(a[i]-b[i])最小。a[i]<=30

思路:首先得到b[i]必然小於60。這個很重要,因為我們列舉的b的集合就是60.首先當b如果都取1,那麼最大的abs就是30,所以b可以取得的極限是60.然後我們可以得到60裡面的所有的素數,這些素數的個數是17.因此我們發現是狀壓dp。

首先預處理出1~60的包含素數的集合,然後列舉a[i],列舉1~60,再列舉1~1<<17即可得出答案。

關鍵:尋找子集範圍,尋找變數的最大範圍

1 #include2

3using

namespace

std;

4const

int inf = 0x3f3f3f3f;5

const

int maxn = 100 + 5;6

const

int u = 1

<< 17;7

struct

pointdp[maxn][u + 5

];10

intf[maxn];

11bool

vis[maxn];

12 vectorv;

13int

n;14

inta[maxn];

15 vectorans;

1617

intmain()24}

25}26int len =v.size();

27//

f[1] = 1;如果單獨變成1了,那麼dp時就無法有多個1了。

28for (int i = 1; i <= 60; i++)

36if (flag) f[i] |= 1

<

38}39 scanf("

%d", &n);

40for (int i = 1; i <= n; i++) scanf("

%d", a +i);

41for (int i = 0; i < u; i++) dp[0][i].val = 0;42

for (int i = 1; i <= n; i++)46}

47for (int i = 1; i <= n; i++)57}

58}59}

6061

int pre = 0, mini = dp[n][0

].val;

62for (int i = 1; i < u; i++)67}

68//

printf("%d\n", dp[n][u - 1].val);

69for (int i = n; i > 0; i--)

75reverse(ans.begin(), ans.end());

76 len =ans.size();

77for (int i = 0; i < len; i++)

80return0;

81 }

view code

然後上面的這個47-59行可以有優化成

for (int i = 1; i <= n; i++)

if (k == 0) break

; }}}

view code

就是先篩選出其中本來就不包含和原子集取&的元素,然後通過列舉k,再&可以消去很多種情況,大大減少時間複雜度。

狀壓DP初探 總結

2018過農曆新年這幾天,學了一下狀態壓縮動態規劃,現在先總結一下。狀態壓縮其實是一種並沒有改變dp本質的優化方法,階段還是要照分,狀態還是老樣子,決策依舊要做,轉移方程還是得列,最優還是最優,無後還是無後,所以它比較好理解。狀壓,顧名思義就是要將一些狀壓想辦法壓縮起來 可以壓,也可以刪 其中這些狀...

狀壓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(總結)狀態壓縮

狀壓這個和二進位制分不開關係 所以,對於二進位制的熟悉是必不可少的技能 與操作,1不變,0變0 或操作,0不變,1變1 異或操作,0不變,1取反 取反操作,把每乙個二進位制位0變1,1變0 還有一些複雜操作可以根據這些去理解 狀態壓縮 所謂狀態壓縮就是把dp的每一次轉移時的狀態用二進位制來表示 或者...