久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

狀壓dp(總結)狀態(tài)壓縮

 小樣樣樣樣樣樣 2022-10-28 發(fā)布于北京

狀壓這個和二進制分不開關系

所以,對于二進制的熟悉是必不可少的技能

&  與操作,,1不變,,0變0    

|  或操作,0不變,,1變1  

^  異或操作,0不變,,1取反   

~ 取反操作,把每一個二進制位0變1,,1變0

還有一些復雜操作可以根據這些去理解

狀態(tài)壓縮

所謂狀態(tài)壓縮就是把dp的每一次轉移時的狀態(tài)用二進制來表示

或者用二進制來間接表示

比如

這里有10個蘋果,,編號1-10

我拿走了1,4,7,9這四個蘋果

那么我們可以用011011010這一串二進制數來表示現在的狀態(tài)

0表示這個位置沒有蘋果,,1表示有

那么這就是一個狀態(tài)

相比拿一個bool型的數組,,這樣表示更方便,,內存更小,操作更簡單

現在我想把拿走的蘋果放回去,,沒拿走的拿走

那么狀態(tài)就變成100100101

直接取反      a=011011010   b=100100101

a==~b;

這時候就充分展示了狀態(tài)壓縮的快捷性

下面我們講一道例題,。。,。,。。

在n*n(n≤20)的方格中放置n個車,,每個車可以攻擊所在的行和列,,求方案總數

直接上排列組合,n,!,,很好理解啊

在n*n(n≤20)的方格棋盤上放置n 個車,某些格子不能放,,求使它們不能互相攻擊的方案總數,。

這時候一些格子不能放,就要考慮每一行的情況

但是   ,,,,,,,即使每一行中有的格子不能放,,最終還是每一行每一列都要有一個車子

所以我們用s這個int型的數來表示現在的狀態(tài)(行狀態(tài))

如果這一列現在有車子,那這一位就是1

所以最終s一定會變成11111111111(全是1)只有這樣才能把n個車全部放進去

這樣這一狀態(tài)有幾個車子說明這就是第幾行

那這樣轉移方程就有了

dp[s]+=dp[s^(s&-s)];

for(;j>0;j-=(j&-j)){
    dp[i]+=dp[i^(j&(-j))];
}

還有個問題,,有些格子不能放車

這怎么辦,??,?,??,?,??,?,??

還記得前面的蘋果嗎

用1表示這里能放車子,,0表示不可以

在狀態(tài)轉移的時候&一下就可以啦

j=i&s[num];

代碼如下

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m;
long long dp[1<<20];
int s[25];
int main(){
	memset(s,0x7fffffff,sizeof(s));
	//if(s[1][1]==1)cout<<"sh";
	//cout<<(s[1][1]&0)<<endl;
	scanf("%d%d",&n,&m);
	int x,y;
	for(int i=1;i<=m;i++){
		scanf("%d%d",&x,&y);
		s[x]-=(1<<(y-1));
	}
	dp[0]=1;
	for(int i=1;i<(1<<n);i++){
		int j,num=0;
		for(j=i;j>0;j-=(j&(-j))){
			num++;
		}
		j=i&s[num];
		for(;j>0;j-=(j&-j)){
			dp[i]+=dp[i^(j&(-j))];
		}
	}
	printf("%lld",dp[(1<<n)-1]);
}

 這樣基本的狀壓dp就結束了

也許你已經發(fā)現了

所有的n都小于等于20

因為int只有32位

這也是狀壓的前提

所以當你一直為空間時間復雜度著急時

就去考慮狀壓

而狀壓前先找到可以狀壓的數

就是32位以內的

over

    本站是提供個人知識管理的網絡存儲空間,,所有內容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現有害或侵權內容,,請點擊一鍵舉報,。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多