中考前乙個學期都沒怎麼碰資訊,終於中考完了,第乙個來學習一下幾個dp。
狀壓dp在提高組好像挺常考,而且我也一直不太會,便來學習一下。
狀壓dp的基礎便是位運算。先來列幾個:
「&」:與運算,二進位制下每一位進行如下運算:1&1=1 1&0=0 0&1=0 0&0=0,如:110&100=100,十進位制下即表示6&4=4。
「|」: 或運算,二進位制下每一位進行如下計算:1|1=1 1|0=1 0|1=1 0|0=0, 如:110|100=110,十進位制之下即表示6|4=6。
「^」:異或運算,二進位制下每一位相同為0,每一位不同即為1,即:1^1=0 1^0=1 0^1=1 0^0=0,如110^100=010,十進位制下表示6^4=2。
「>>」:向右位移,即將此二進位制數向右減少幾位,如1110001>>3=1110
"<<":向左位移,即將此二進位制數向左增加幾位,如110<<3=110000
大體上就這幾種了,優先順序為'~' > '&' > '^' > '|',位移最好加括號。
上面符號在c++中使用時編譯器會先將十進位制轉換為二進位制,運算後再轉為十進位制,全是自動的。
1、n>>1:將n除以2
2、n<<1:將n乘以2
注:聽說這用兩種運算比直接用*和/更快一些
3、if( ( 1<< (i-1) )&x > 0 ):判斷數x的第i位是否為1,若大於0,則為1,反之不是。
其實很好理解,就是人為創造乙個只有第i位為1的數,並將此數與x進行一次&運算,因為構造的數前i-1位為0,故運算後的數前i-1位全為0,若x的第i位為1,則1&1=1>0,為0,則0&1=0
4、x=x|( 1<< ( i-1 ) ):將數x二進位制下的第i位改為1。
和上面乙個差不多,構造乙個只有第i位為1的數,將x與其做|運算,因為1|0=1,0|0=0,所以x前i-1不變,又因1|1=1,0|1=1,無論怎樣x的第i位為1或0,都將變為1。
5、x=x&(x-1):去掉數x從右往左數第乙個1。
好難證明,我又蒻又懶,就不證了吧逃
貌似常用的這麼多,歡迎大佬指責補充
怎麼做題當然最重要啦。
其實狀壓dp說白了就是將方案用二進位制暴力列舉出來,也不要害怕,且是否用狀壓dp,dp的方程一般都挺好看的,可能是我太弱了沒做過狀壓難題,比較好入門。
一般看來,狀壓dp的題資料範圍極小一般只有15-50。且瞄一眼發現沒有什麼思路或發現無法進行爆搜,這是基本肯定是狀壓dp了。狀壓dp複雜度極大為2的指數級別,但搜尋將更大,故其還是很重要的。大體套路是:讀題看資料範圍,用二進位制表示狀態(與常規dp不同之處),寫出狀態轉移方程,注意臨界情況及細節,編寫程式。
1、(usaco2006nov) 玉公尺田 洛谷p1879 (題解)
2、(scoi2005)互不侵犯 洛谷p1896 (題解)
3、(sdoi2006)最短距離 洛谷p2453 (題解)
會陸續補充
狀態壓縮dp入門
poj1321 我們可以把棋盤的每一行看做是乙個狀態,如果某一列放置了棋子,那麼就標記為1,否則就標記為0.然後把它看成是乙個二進位制數,然後轉為10進製數,就可以當做陣列下標然後進行狀態轉移了 設dp i s 為處理到第i行時,狀態為s的方法數 那麼我們列舉第i 1行的所有狀態s dp i s d...
狀態壓縮DP入門題
在n n n 20 的方格棋盤上放置n 個車 可以攻擊所在行 列 求使它們不 能互相攻擊的方案總數。僅供和我一樣的菜鳥們參考 以n 4為例子解析原始碼 include include using namespace std int64 a 1100000 int main cout 前乙個狀態壓縮的...
狀態壓縮dp入門題目
題目大意是有m n的玉公尺地,但其中有些是不肥沃的,不能種植。用1來代表肥沃,0代表不肥沃。另外奶牛不喜歡挨著吃,也就是說要間隔著種植,求有幾種種植方式,並將計算結果對1e8取模。include include using namespace std int dp 12 1 12 dp i s 第i...