位壓縮是通過k進製的一位來表示資料中乙個狀態的一種儲存壓縮方式,它可以在常數級上優化乙個演算法,例如我們通常所說的狀態壓縮動態規劃,就是用二進位制中的一位來表示所求問題中的乙個中間狀態,當然這樣描述還是比較抽象的。
換個例子,對於乙個圖來說,如果我們只關心兩個邊之間的相鄰關係,那麼我們實際上可以用乙個二進位制位來表示,用0,表示兩點之間沒有邊,而用1表示兩點之間存在一條邊,那麼我們就可以用乙個長的二進位制串來表示某一點與其他所有點的相鄰關係,而二進位制串的長度就是所有頂點的個數。這樣就比我們直接使用二維陣列的空間時間複雜度降低了乙個常數級別(32倍),而c++中有乙個資料結構就是bitset<32>,它可以用來初始化乙個位數為32的二進位制串,實際上bitset的長度是比較靈活的,我們可以將32換成其他的任意常數,用來表示長度位該常數的二進位制串,這樣上面用二維陣列描述的圖結構就可以換成 bitsetmat[n]來表示,注意n一定是乙個常數,而不能是乙個變數。
通過使用位壓縮,我們可以將對於基本資料型別的操作轉變成對位的運算,這樣我們只需要掌握bitset的常用操作即可。
bitset儲存二進位制數字。
bitset就像乙個bool型別的陣列一樣,但是有空間優化——bitset中的乙個元素一般只佔1 bit,相當於乙個char元素所佔空間的八分之一。
bitset中的每個元素都能單獨被訪問,例如對於乙個叫做foo的bitset,表示式foo[3]訪問了它的第4個元素,就像陣列一樣。
bitset有乙個特性:整數型別和布林陣列都能轉化成bitset。
bitset的大小在編譯時就需要確定。如果你想要不確定長度的bitset,請使用(奇葩的)vector
1. 位運算都可以用: 與、或、非、異或,左移,右移
2. foo&foo2
3. foo|foo2
4.~foo
5. foo^foo2
6. foo<<=
27. foo>>=
28. foo.
size
() 返回大小(位數)
9. foo.
count
() 返回1的個數
10. foo.
any(
) 返回是否有1
11. foo.
none
() 返回是否沒有1
12. foo.
set(
) 全都變成1
13. foo.
set(p) 將第p +
1位變成1
14. foo.
set(p, x) 將第p +
1位變成x
15. foo.
reset
() 全都變成0
16. foo.
reset
(p) 將第p +
1位變成0
17. foo.
flip
() 全都取反
18. foo.
flip
(p) 將第p +
1位取反
19. foo.
to_ulong
() 返回它轉換為unsigned
long的結果,如果超出範圍則報錯
20. foo.
to_ullong
() 返回它轉換為unsigned
long
long的結果,如果超出範圍則報錯
21. foo.
to_string
() 返回它轉換為string的結果
乙個連通圖中三元組的最小度數
class
solution
int num[n+1]
;for
(int i=
1;i1;i++
)num[i]
=mat[i]
.count()
;//統計每個頂點的度數
int ans=int_max;
//bitset本質上是乙個二進位制數,所以我們操作bitset資料時,我們除了使用內建函式以外
//我們都可以用位運算來計算;
for(
int i=
1;i1;i++)}
}}return ans==int_max?-1
:ans;}}
;
神奇的常數優化
話說noip不開優化,那我們來看看開優化後會發生什麼 乙個簡單的累加 include include 計時看看差別 includeusing namespace std int main 按理來說,上面的兩種方法差不多 在devc 5.7.1中,xp系統 學校機房的那種 不開任何優化 大約前一種是8...
神奇的常數優化
話說noip不開優化,那我們來看看開優化後會發生什麼 乙個簡單的累加 include include 計時看看差別 includeusing namespace std intmain 按理來說,上面的兩種方法差不多 在devc 5.7.1中,xp系統 學校機房的那種 不開任何優化 大約前一種是85...
矩陣乘法的常數優化
矩陣乘法的常數優化 philipsweng 雖然說作為鍵盤科學家,我們更應該關心程式的時間複雜度。但是乙個寫的不好的程式可能在實際執行會跟時間複雜度更差的程式差不了多少。我們我們也應該注意程式的常數優化。對於矩陣乘法來講。我們實際上可以比較這兩種打法。實際上第二種打法在絕大多數情況下效率約為第一種的...