CH 0301遞迴實現指數型列舉

2021-09-18 06:49:44 字數 3458 閱讀 4769

描述

從 1~n 這 n(n<16) 個整數中隨機選取任意多個,輸出所有可能的選擇方案。

輸入格式

乙個整數n。

輸出格式

每行一種方案。同一行內的數必須公升序排列,相鄰兩個數用恰好1個空格隔開。對於沒有選任何數的方案,輸出空行。本題有自定義校驗器(spj),各行(不同方案)之間的順序任意

樣例輸入

3
樣例輸出
3

22 3

11 3

1 21 2 3

hb的部落格傳送門總結的很好,跟著也寫一寫,練習一下

之所以叫指數型列舉,就是所有的數都可以選或者不選,數量就是2

n2^n

2n求前n個數的真子集

思路:

深搜,每個數可以選或不選,那麼我們可以列舉選幾個,比如n=3我們可以選0,1,2,3,對選出的數進行遞迴,這樣就可以得到選幾個的所有方案

遞迴實現:

#include

#include

using namespace std;

static

const

auto io_sync_off =

()()

;const

int manx =17;

int n, num[17]

;bool vis[17]

;void

dfs(

int cur,

int tar)

for(

int i =

1; i <= n;

++i)

}int

main()

但是這樣是所有的可能情況比如選2個,結果中兩個數的情況有12,13,21,23,31,32,達到的是ch0303全排列的效果,為什麼會這樣呢(明明是我先來的(白學警告)),其實就是這樣比如12先來了,後面的21就不用來了,因為結果是相同的,都選了這兩個數,只是順序不同,我們不需要管順序,因為題目要求是選任意多個,主要是求多個中有些多個

省去上面那堆囉嗦簡單一句就是集合中是同乙個集合

解決方法就是題目要求的按公升序輸出,為了達到判題(spj)的效果(這個spj中怎麼處理輸入的後面也要研究一下)

公升序那麼直接比較當前要選數和上乙個位置數的大小,小continue就行了

if

(i < num[cur -1]

)//替換/*********/

continue

;

二進位制位運算代替陣列:

位運算這個方面真的很重要,要多練習,狀態壓縮,賦值都可以大大簡化

但是這裡有乙個問題,上述方法中cur代表的是當前的位置,而在二進位制替換陣列的情況下cur僅僅代表的是有幾個數被賦值了,並不能代表位置,所以比較當前值和上乙個位置值大小的方法就不管用了,解決方法就是加乙個start代表當前數從幾開始往上累加

不過還有一種方法就是你的cur不是代表賦值了幾個數嘛,那麼不就是表明賦值了幾個數就該從幾開始加了嘛,所以讓icur開始就可以了,還有一些注意事項見**

而且這種做法是不需要vis陣列的,因為每次都是從上一次數的加一開始,必定不重複

#include

#include

using namespace std;

static

const

auto io_sync_off =

()()

;int n;

void

dfs(

int cur,

int tar,

int num)

for(

int i = cur; i < n;

++i)

dfs(i +

1, tar, num |

1<< i)

;// 注意傳進i + 1,位運算表示把num第i位賦值為1

}int

main()

vector遞迴

也就是書中的方法,綜合上面的從當前位置cur開始,以及選與不選的遞迴,簡潔明瞭

#include

#include

using namespace std;

static

const

auto io_sync_off =

()()

;int n;

vector<

int> nums;

void

infer

(int cur)

infer

(cur +1)

;//不選

nums.

push_back

(cur)

;infer

(cur +1)

;//選

nums.

pop_back()

;}intmain()

狀態壓縮

列舉所有的2

n2^n

2n種可能,1代表選0代表不選

#include

#include

using namespace std;

static

const

auto io_sync_off =

()()

;int

main()

return0;

}

狀態壓縮遞迴

綜合狀態壓縮、書上遞迴中選與不選和直接從cur位置開始的方法

#include

#include

using namespace std;

static

const

auto io_sync_off =

()()

;int n;

void

dfs(

int cur,

int num)

dfs(cur +

1, num)

;//不選

dfs(cur +

1, num |

1<< cur)

;//選

}int

main()

0301 遞迴實現指數型列舉

本題可以用乙個遞迴思路解決。每乙個數都有放或者不放兩種狀態。其實本題還可以用乙個思路解決。一定有2 n種排列方案。所以可以通過位列舉來列舉出所有的可能排列。include stdio.h include string.h include math.h include vector include a...

遞迴實現指數型列舉

從 1 n 這 n 個整數中隨機選取任意多個,輸出所有可能的選擇方案。輸入格式 輸入乙個整數 n。輸出格式 每行輸出一種方案。同一行內的數必須公升序排列,相鄰兩個數用恰好1個空格隔開。對於沒有選任何數的方案,輸出空行。本題有自定義校驗器 spj 各行 不同方案 之間的順序任意。資料範圍1 n 15 ...

遞迴實現指數型列舉

從 1 n 這 n 個整數中隨機選取任意多個,輸出所有可能的選擇方案。輸入乙個整數n。每行輸出一種方案。同一行內的數必須公升序排列,相鄰兩個數用恰好1個空格隔開。對於沒有選任何數的方案,輸出空行。本題有自定義校驗器 spj 各行 不同方案 之間的順序任意。1 n 15 1 n 15 1 n 15 3...