利用位運算解決組合問題

2021-09-29 16:27:33 字數 2437 閱讀 7587

求n個資料的組合:

由數學知識,可以知道一共有2n個子集

用二進位制進行對照會非常直觀

子集空集

a1a0

a1 , a0

a2a2, a0

a2, a1

a0,a1, a2

二進位制數

0 0 0

0 1 0

0 0 1

0 1 1

1 0 0

1 0 1

1 1 0

1 1 1

給出n個資料,問從這n個資料中取出3個組成三角形,有多少種取法?

經典的組合問題

下面上**

while

(kk)

//統計1的個數

例如:1011

&(1011-1

)=1010

1010&(

1010-1

)=1010

&1001

=1000..

..

完整**

#include

//萬能標頭檔案

using

namespace std;

int sd[

100001];

// 定義乙個儲存邊的陣列

int jmt[3]

;//儲存陣列

bool

judge

(int

* a)

//判斷函式

intmain()

//輸入資料

for(

int i =

0; i<(1

<; i++

)//統計1的個數

if(counted==3)

}}if(

judge

(jmt)

)num++

;memset

(jmt,0,

sizeof

(jmt));

//清零

} cout

}

由於此種解法的時間複雜度為2n,因此對於此題應該換一種解法

這裡考慮用dfs的方法(本質為三層for迴圈)

以下是**

#include

using

namespace std;

int state , n , counted;

int book[

2501];

int arr[

2501

], jmt[3]

;bool

judge

(int

* a)

void

dfs(

int state)

else

if(state<3)

for(

int i =

0; i < n ; i++)}

return;}

intmain()

dfs(0)

; cout<6

}

此種解法如果時間限制為1s的話,仍然無法達到要求,因此應該考慮更加高階的演算法,下面的演算法是sort快排+二分搜尋。

下面上**

#include

//萬能標頭檔案

using

namespace std;

int sd[

2501];

int jmt[3]

;int book[

2501];

//判重陣列

int counted;

bool

judge

(int

* a)

//判斷函式

intsrh

(int

* arr ,

int num ,

int start ,

int end)

//二分搜尋函式

return-1

;//沒搜尋到,返回-1

}int

main()

sort

(sd,sd+n)

;//進行快排,使序列由小到大進行排列,使得可以使用二分法

for(

int i =

0; i < n ; i++)}

}else

//沒搜尋到的話,進行遍歷

for(

int k =

0; k < n ; k++)}

}memset

(book,0,

sizeof

(book));

//清零進行下一步迴圈迭代

} cout<2

return0;

}

利用位運算解決排序問題(摘自程式設計珠璣)

問題背景 已知資料的取值範圍在0 10000000,且所取資料不重複,將輸入的資料排序並盡可能的使用少的記憶體空間 define bitsperrword 32 define shift 5 define mask 0x1f define n 10000000 include int a 1 n b...

位運算解決N 皇后問題

描述 位運算是定義在整數上的運算。但在做位運算的時候,並不把整數看作整數,而是將它們看做一系列二進位制數字,逐位進行運算。位運算有6種,他們的名稱,運算子及運算規則如下 與 and 5 6 4 101 110 100 或 or 5 6 7 101 110 111 異或 xor 5 6 3 101 1...

C 利用棧解決運算問題

2017 06 27 19 19 18 第一步需要將中綴表示式轉為字尾表示式。這步的轉化可以說是本題的核心。主要的轉化手段是利用棧,有如下幾個規則 int toint stringin int priority chara bool isdig char a 保證每次入棧的符號的優先順序都比當前的棧...