狀態壓縮刷題

2022-03-16 13:40:34 字數 2907 閱讀 4084

所謂狀態壓縮,大多數就是用二進位制01形式將狀態表示出來,運用位運算完成狀態的檢視和轉移;基本上資料範圍是n<=15;

這是很裸的狀態壓縮。我們要關閉所有的開關,但是開關是相連的;

有乙個很好地條件是,開關最多能波及到兩層;乙個開關的變化,直接關聯的會變化,間接變化的也會變,但是間接變化的不會再傳遞下去;

所以我們將每個開關關掉後的狀態記錄下來;

設二進位制1是關閉狀態,當狀態變為0時更新答案即可;

要排除自己關自己的情況;

二進位制列舉關哪乙個就行了;

乙個開關不需要關兩遍及以上,相當於沒幹什麼;

#include#include

#include

using

namespace

std;

const

int maxn=1e6+10

;int

res[maxn];

int a[30][30

];int

n;int ans=2147483647

;void dfs(int x,int now,int

cnt)

return

; }

dfs(x+1

,now,cnt);

now^=res[x];

dfs(x+1,now,cnt+1

); now^=res[x];

}int

main()

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

}}

//int sum=0;

int sum=(1

<

;

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

view code

這道題的狀態比上面的題多一點點,但是基本模擬;不同的是我們這次用dp轉移。

設f[i]為當前為i狀態時,最少關燈次數;

二進位制數1表示燈開著,f[0]為答案;

每次判斷每個按鍵能控制的燈,按完後的狀態為now,從按之前的轉移過來;

(1<

#include#include

#include

using

namespace

std;

const

int maxn=2e5+10

;int

n,m;

int a[120][120

];int

f[maxn];

intmain()

}memset(f,

0x7f,sizeof

(f));

f[(1<1]=0

;

for(int i=(1

<1;i>=0;i--)

f[now]=min(f[now],f[i]+1

); }

}if(f[0]==2139062143) printf("-1"

);

else printf("

%d",f[0

]);

return0;

}

view code

我們需要的是方案數,dp跑不了;

怎麼設計狀態?

設f[i][j]為第i頭牛再隊尾時,情況為j時的合法方案數;

二進位制1表示牛在佇列裡;

我們列舉哪頭牛再隊尾的情況;

再列舉哪頭牛再他的前面,狀態直接搬運過來;

初始化 佇列中只有一頭牛的方案數為1;

列舉時判斷混亂條件;

最後的答案是加和;

#include#include

#include

#include

using

namespace

std;

const

int maxn=1e5+10

;typedef

long

long

ll;ll f[

20][maxn];

intn,x;

int a[20

];ll ans;

intmain()

for(int i=1;i<1}}

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

printf(

"%lld

",ans);

return0;

}

view code

這個題是狀態壓縮+期望;

將每個物品的前提條件狀態壓縮存起來,當前狀態能吃的時候比較一下即可;

設f[i][j]表示在第1輪到第i−1輪內寶物是否取過的狀態為j,第i輪到第k輪的最大期望得分。

但是我們需要逆推,因為正著列舉有些狀態是並沒有被算出來的;

如果當前狀態能選當前物品

f[i][j]+=max(f[i+1][j],f[i+1][j|(1<

下一輪是要選k的,才能加上p[k];

每次都要/n,因為選k的概率是1/n;

#include#include

#include

using

namespace

std;

typedef

double

dd;dd f[

110][1

<<15

];int

k,n;

int p[20

];int res[20

];int

main()

}for(int i=k;i>=1;i--)

else f[i][j]+=f[i+1

][j];

}f[i][j]/=(dd)n;}}

printf(

"%.6lf

",f[1][0

]);

return0;

}

view code

狀態壓縮DP入門題

在n n n 20 的方格棋盤上放置n 個車 可以攻擊所在行 列 求使它們不 能互相攻擊的方案總數。僅供和我一樣的菜鳥們參考 以n 4為例子解析原始碼 include include using namespace std int64 a 1100000 int main cout 前乙個狀態壓縮的...

狀態壓縮DP入門題

1 本題為狀態壓縮題 2題目大意 3乙個矩陣裡有很多格仔,每個格仔有兩種狀態,可以放牧和不可以放牧,4可以放牧用1表示,否則用0表示,在這塊牧場放牛,要求兩個相鄰的方 5格不能同時放牛 不包括斜著的 即牛與牛不能相鄰。問有多少種放牛方 6案 一頭牛都不放也是一種方案 7要列舉每一行中的是否種植 也就...

刷題刷題 京東

題目 二維陣列為三列多行是陣列,每行存有三個數字,分別用ai,bi,ci標示 當某行的三個數字全都小於另一行的三個數字時,即 ai思路 對於第一列反向排序,保證第一列數從大到小排序。之後用後面的行依次與前面的行進行對比,將無效行的價值置為零。include include includelong l...