題解 星空 狀壓DP

2021-09-28 21:14:41 字數 2262 閱讀 9392

這道題思維難度非常高,有很多處理的小技巧,並且**也有很多細節 ;

這道題是一種序列的區間操作,我們都知道,區間操作比較麻煩,所以我們要想辦法將區間操作轉換成單點修改;

這時,我們想到了差分,假如我們對乙個序列進行操作,這時乙個序列裡的相對狀態不會變只有兩端改變,換句話說就是這個序列的差分並不會發生改變,只有兩端的差分陣列會發生變化。但這裡的差分並不是差

而是異或;對乙個區間[l,r]進行修改操作就是將差分陣列c[l],c[r+1]取反,最後我們的目標就是要將差分陣列全部變成0;

但這裡就有乙個細節:差分陣列全部變成0的意思就是所有的狀態都是一樣的,但有可能全部亮或者全不亮;這裡我們要假設第0個燈泡是亮的;然後差分出來才是合法的全亮狀態;

還有乙個細節:差分陣列要開到n+1來保證至少有偶數個數的1,這樣才能消去 ;

所以我們就這樣完成了第一步,將區間修改轉化成單點修改;

處理出來差分陣列之後,我們就要將這個序列全部變為0 ;

有兩種情況;乙個0乙個1,這樣操作之後1的個數沒有變 ;

兩個都是1,這種情況就是減少兩個1

但大多數情況並不能一次操作就完成,因為只能操作m種長度 ;

所以實際情況是1先和一些0交換,然後兩個1一起消去 ;

所以對所有1跑一邊bfs處理出到與其他1消去所需要的步數;

bfso(n)就可以完成;

處理完每個1與其他1消去之後,就要考慮如何選擇使其代價最少 ;

我們可以注意到其實原來的1很少不超過16個,於是我們可以開始考慮狀壓dp ;

我們反著dp;

dp[i]表示狀態為i到狀態為0所需要的最小步數 ;

初始化dp[0]=0 ;

然後倒著列舉點亮哪兩個燈,(因為倒著來是點亮,正著來就是消去兩個燈)

然後點亮完了的狀態就是i|(1最後再輸出dp[最初的狀態] ;

到此,這道題就順利的解決了;

具體細節請看**:

#include

using

namespace std;

const

int maxn =

40101

;int n,k,m ;

int a[maxn]

,c[maxn]

,dis[20]

[maxn]

;int len[maxn]

,sta[maxn]

,top=0;

int dp[

1<<17]

;bool vis[maxn]

;inline

void

read

(int

&x)while

(s>=

'0'&&s<=

'9')

x*=f ;

}void

bfs(

int s,

int*dis)

y=x+len[i];if

(y<=n+1&&

!vis[y])}

}}intgetdis

(int x,

int y)

intmain()

for(

int i=

1;i<=n+1;

++i) c[i]

=a[i]

^a[i-1]

;for

(int i=

1;i<=m;

++i)

read

(len[i]);

memset

(dis,

0x3f

,sizeof

(dis));

memset

(dp,

0x3f

,sizeof

(dp));

for(

int i=

1;i<=n+1;

++i)

if(c[i]

) sta[

++top]

=i,bfs

(i,dis[top]);

dp[0]

=0;for

(int i=

0,t=(1

<

;i++i)

for(

int j=fir+

1;j++j)}}

printf

("%d"

,dp[(1

<

]);return0;

}

星空 差分,狀壓dp

總算不再是能用暴力卡常 隨機化水過的好t3了。說是打了兩個標籤,實際上最關鍵的是題意轉化。如果你絲毫不轉化的話也可以 1 include2 using namespace std 3int dp 2 1048577 b 65 k,n,m,x 9 f 1 mx 4int main 15 printf ...

狀壓dp題解

實現 includeconst int maxn 1 20 1 typedef long long ll ll f maxn a 25 a x 記錄第x行的障礙狀態 int lowbit int x int main f 0 1 乙個也不放也是一種方案 int maxs 1 判斷當前狀態下狀態的1的...

題解 Vjestica (狀壓DP)

有n個字元合集,求其字首樹的最少結點個數。資料範圍 n 16,1 m 1000000 字元個數 首先看到 n 16 可知,這道題是狀壓dp或者暴力 狀態是什麼?因為是n的資料範圍小,n為字元合集個數,所以狀態是 n個字元合集的整體 的選擇情況,這裡用s表示,二進位制範圍為 1 11111111111...