描述
從 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
不是代表賦值了幾個數嘛,那麼不就是表明賦值了幾個數就該從幾開始加了嘛,所以讓i
從cur
開始就可以了,還有一些注意事項見**
而且這種做法是不需要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...