狀壓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 #include2view code3using
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 }
然後上面的這個47-59行可以有優化成
for (int i = 1; i <= n; i++)view codeif (k == 0) break
; }}}
就是先篩選出其中本來就不包含和原子集取&的元素,然後通過列舉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的每一次轉移時的狀態用二進位制來表示 或者...