洛谷P3943 星空

2022-03-29 16:02:03 字數 2851 閱讀 6595

洛谷p3943 星空

命運偷走如果只留下結果, 時間偷走初衷只留下了苦衷。

你來過,然後你走後,只留下星空。

逃不掉的那一天還是來了,小 f 看著夜空發呆。

天上空蕩蕩的,沒有一顆星星——大概是因為天上吹不散的烏雲吧。

心裡吹不散的烏雲,就讓它在那裡吧,反正也沒有機會去改變什麼了。

小 c 拿來了一長串星型小燈泡,假裝是星星,遞給小 f,想讓小 f 開心一點。

不過,有 著強迫症的小 f 發現,這串一共 n 個燈泡的燈泡串上有 k 個燈泡沒有被點亮。

小 f 決定 和小 c 一起把這個燈泡串全部點亮。

不過,也許是因為過於笨拙,小 f 只能將其中連續一段的燈泡狀態給翻轉——點亮暗燈 泡,熄滅亮燈泡。

經過摸索,小 f 發現他一共能夠翻轉 m 種長度的燈泡段中燈泡的狀態。

小 c 和小 f 最終花了很長很長很長很長很長很長的時間把所有燈泡給全部點亮了。

他 們想知道他們是不是蠢了,因此他們找到了你,讓你幫忙算算:在最優的情況下,至少需要 幾次操作才能把整個燈泡串給點亮?

輸入格式:

從標準輸入中讀入資料。

輸入第 1 行三個正整數 n,k,m。

輸入第 2 行 $k$ 個正整數,第 i 個數表示第 i 個被沒點亮的燈泡的位置 $a_i$。

輸入第 3 行 $m$ 個正整數,第 i 個數表示第 i 種操作的長度 $b_i$。

保證所有 $b_i$​互不相同;保證對於 $1 \le i < k$,有 $a_i< a_$;保證輸入資料有解。

輸出格式:

輸出標準輸入中。

輸出一行乙個非負整數,表示最少操作次數。

輸入樣例: 

5 2 2 

1 5

3 4

輸出樣例: 

2
【樣例 1 解釋】

【資料範圍與約定】

子任務會給出部分測試資料的特點。如果你在解決題目中遇到了困難,可以嘗試只解 決一部分測試資料。

每個測試點的資料規模及特點如下表

特殊性質:保證答案小於 4

一道狀壓$dp$好題。

首先發現$n$特別的大,但是$k$特別小,顯然是要在$k$上面做文章。

注意到$k\leq8$,感覺有點狀壓$dp$的樣子啊。

我們先對原序列進行異或差分。

異或差分是啥?$emmmm\cdots\cdots$

假如有乙個$01$序列$10010101$,對其進行異或差分得到了$110111111$。

注意末尾多了一位。

有什麼用呢?

我們可以發現,當我們要對$[l,r]$進行區間異或時,我們只需要對$l-1,r$這兩個點異或就好。

於是現在我們要求的就變成了:

將異或序列每次取反兩個間隔一定的點,求序列中所有元素變成$0$的最小次數。

而我們一次在兩個$0$上取反沒有任何意義。

所以每一次修改要麼是把兩個$1$變成$0$,要麼是乙個$0$變$1$,乙個$1$變$0$。

如果是後者,我們可以把它看成前面的$1$往後跳了一段。

但是最後還是要和另外乙個$1$同時消掉。

於是就變成了點與點之間兩兩配對求最小代價的問題。

點與點之間匹配的最小代價可以跑$spfa$搞出來。

當然這個匹配不是二分圖匹配。。。

這個匹配時一般圖帶權匹配。

但是這玩意好像要用帶花樹啊。。。

蒟蒻表示根本不會。。。

($ps$:一般圖帶權匹配可以去$uoj$找板子。。。我這個菜雞就算了。。。)

那怎麼辦???

等一下!有效點數好像不超過$16$?

我們可以狀壓$dp$啊!

複雜度表面上是$o(2^kk^2)$。

但是我們發現我們只要按順序找到一對沒有匹配過的點直接轉移就可以了。

所以複雜度實際上是$o(2^kk)$。

仍然可以遍歷所有狀態。

於是這個題被$\text+spfa+\textdp$完美搞定。

一開始把$m,k$的讀入順序搞反了還$wa$了一發。。。

我的**裡$k$換成了$q$,注意一下。

附**:

#include#include#include#include#include#define maxn 40010

#define maxm 70

#define maxk 20

using namespace std;

int n,m,q;

int a[maxn],b[maxm],path[maxn],pos[maxk],dis[maxk][maxk],dp[1

while(c>='0'&&c<='9')

return date*w;

}void spfa(int x)

if(u-b[i]>=1&&!path[u-b[i]])

} }for(int i=1;i<=q;i++)dis[x][i]=path[pos[i]]-1;

}void work()

break;

} printf("%d\n",dp[s]);

}void init()

q=0;

for(int i=1;i<=n;i++)if(a[i])pos[++q]=i;

for(int i=1;i<=m;i++)b[i]=read();

for(int i=1;i<=q;i++)spfa(i);

}int main()

洛谷 P3943 星空

有乙個長度為n的01序列,有k個1 每次可以將給定長度的子串取反,即0 1,1 0 求最少幾次可以將整個序列都變為0 差分 狀壓dp 首先將原序列異或差分 每消去一對1就是將1移到一起 先用bfs預處理出每兩個1移到一起的最小步數 然後用狀壓dp來求總的最小步數 include include co...

洛谷 P3943 星空

命運偷走如果只留下結果,時間偷走初衷只留下了苦衷。你來過,然後你走後,只留下星空。逃不掉的那一天還是來了,小 f 看著夜空發呆。天上空蕩蕩的,沒有一顆星星 大概是因為天上吹不散的烏雲吧。心裡吹不散的烏雲,就讓它在那裡吧,反正也沒有機會去改變什麼了。小 c 拿來了一長串星型小燈泡,假裝是星星,遞給小 ...

洛谷P3943 星空 題解

一道很好的鍛鍊思維難度的題,如果您能在考場上直接想出來的話,提高組450分以上就沒問題了吧。別像作者一樣看了好幾篇題解才勉強會 先提取出題目大意 給定乙個長度n 40000的01串,其中1的個數 8,有m種操作,每次操作都是把乙個該操作對應長度的區間取反,或者說異或上1,求使整個串變為只有0的串的最...