傳送門
感覺真的是一道挺有質量的好題,練到了。
我就不囉嗦部分分了,直接說正解吧。
第一印象:資料範圍k≤8
k\leq8
k≤8,標籤上說也許是個狀壓dp
正式思考:首先發現乙個事情:把一段區間取反非常麻煩。我們可以考慮類似差分的思想,處理出d[i
]=a[
i]xo
ra[i
+1
]d[i]=a[i]\ xor\ a[i + 1]
d[i]=a
[i]x
ora[
i+1]
,於是將區間取反就變成了d
dd上的兩個端點取反。
那麼問題就轉化為:給定乙個01
0101
串和乙個距離集合l
ll,每次可以選兩個位置i
ii和j
jj將它們取反,但是必須滿足∣j−
i∣∈l
|j-i|\in l
∣j−i∣∈
l,問最少要操作多少次才能把它們全部變成1。
考慮將兩個位置上的數取反:
所以問題又轉化為:乙個n
nn個頂點的無向圖,有不超過2k2k
2k個點上有妹子;每次可以讓乙個點上的妹子走到另乙個點,但是走的距離有限制;兩個妹子碰到一起就都是你的了;問至少要操作多少次才能泡遍所有妹子。皮這一下十分開心
要讓兩個妹子走到一起並且操作次數盡量少,顯然要走最短路。所以就先spfa(或者可以看做乙個簡單bfs)求出每個有妹子的點到其它所有點的最短距離。複雜度o(n
mk
)o(nmk)
o(nmk)
。於是問題最終轉化為:有不超過2k2k
2k個物品,選擇其中兩個可以花一定代價消去,問最小代價和。
簡單狀壓dp即可。
有乙個小細節需要注意:對於當前狀態s
ss,可以列舉兩個不在s
ss中的物品i,j
i,ji,
j進行拓展,如果直接這樣列舉複雜度是o(k
222k
)o(k^22^)
o(k222
k)的,在某些題中可能被卡(本題應該可以過)。乙個常見優化是,物品i
ii就直接選擇不在s
ss中的編號最小的物品,而不是列舉i
ii,這樣的話複雜度就是o(k
∗22k
)o(k*2^)
o(k∗22
k)。
#include
#include
#include
#include
#include
template
<
typename t>
inline
void
read
(t& t)
inline
intread()
#if __cplusplus >= 201103l
template
<
typename t,
typename..
. args>
inline
void
read
(t& t, args&..
. args)
#else
template
<
typename t1,
typename t2>
inline
void
read
(t1& t1, t2& t2)
template
<
typename t1,
typename t2,
typename t3>
inline
void
read
(t1& t1, t2& t2, t3& t3)
template
<
typename t1,
typename t2,
typename t3,
typename t4>
inline
void
read
(t1& t1, t2& t2, t3& t3, t4& t4)
template
<
typename t1,
typename t2,
typename t3,
typename t4,
typename t5>
inline
void
read
(t1& t1, t2& t2, t3& t3, t4& t4, t5& t5)
#endif
// c++11
#ifdef win32
#define llio "%i64d"
#else
#define llio "%lld"
#endif
// win32 long long
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define rrep(i, a, b) for (int i = (a); i >= (b); --i)
#define erep(i, x) for (int i = head[x]; i; i = next[i])
const
int maxn =
4e4+
207;
const
int inf = int_max >>3;
int a[maxn]
, b[maxn]
;int dist[20]
[maxn]
, pos[maxn]
;int dp[
1<<18]
;int n, m, k, zero;
inline
void
spfa
(int ss)}}
void
dfs(
int s)}}
intmain()
洛谷P3943 星空 題解
一道很好的鍛鍊思維難度的題,如果您能在考場上直接想出來的話,提高組450分以上就沒問題了吧。別像作者一樣看了好幾篇題解才勉強會 先提取出題目大意 給定乙個長度n 40000的01串,其中1的個數 8,有m種操作,每次操作都是把乙個該操作對應長度的區間取反,或者說異或上1,求使整個串變為只有0的串的最...
洛谷P3943 星空
洛谷p3943 星空 命運偷走如果只留下結果,時間偷走初衷只留下了苦衷。你來過,然後你走後,只留下星空。逃不掉的那一天還是來了,小 f 看著夜空發呆。天上空蕩蕩的,沒有一顆星星 大概是因為天上吹不散的烏雲吧。心裡吹不散的烏雲,就讓它在那裡吧,反正也沒有機會去改變什麼了。小 c 拿來了一長串星型小燈泡...
洛谷 P3943 星空
有乙個長度為n的01序列,有k個1 每次可以將給定長度的子串取反,即0 1,1 0 求最少幾次可以將整個序列都變為0 差分 狀壓dp 首先將原序列異或差分 每消去一對1就是將1移到一起 先用bfs預處理出每兩個1移到一起的最小步數 然後用狀壓dp來求總的最小步數 include include co...