信息学奥赛一本通(1317:【例5.2】组合的输出)
1317:【例5.2】組合的輸出
時間限制: 1000 ms ??? ??? 內存限制: 65536 KB
提交數: 21154 ??? 通過數: 10292
【題目描述】
排列與組合是常用的數學方法,其中組合就是從n個元素中抽出r個元素(不分順序且r≤n),我們可以簡單地將n個元素理解為自然數1,2,…,n,從中任取r個數。
現要求你用遞歸的方法輸出所有組合。
例如n=5,r=3,所有組合為:
1 2 3 ? 1 2 4 ? 1 2 5 ? 1 3 4 ? 1 3 5 ? 1 4 5 ? 2 3 4 ? 2 3 5 ? 2 4 5 ? 3 4 5
【輸入】
一行兩個自然數n、r(1<n<21,1≤r≤n)。
【輸出】
所有的組合,每一個組合占一行且其中的元素按由小到大的順序排列,每個元素占三個字符的位置,所有的組合也按字典順序。
【輸入樣例】
5 3【輸出樣例】
1 2 31 2 41 2 51 3 41 3 51 4 52 3 42 3 52 4 53 4 5【分析】
? ? ? ? 如果不考慮樣例輸入,只考慮樣例輸出,使用枚舉法,直接可以輸出結果。代碼如下:
#include <stdio.h> int main() {int a,b,c;for(a=1;a<=5;a++)for(b=1;b<=5;b++)for(c=1;c<=5;c++){if(a<b && b<c)printf("%d %d %d\n",a,b,c);}return 0; }? ? ? ? 現在考慮輸入,怎么枚舉呢?實際上就是3個坑,分別用1~5的數進行填充。第一個坑,可能填充的數自然是1、2、3、4、5開頭,由于需要按字典序,所以4和5開頭不用考慮,因為不夠三個。現在只剩下1、2、3三個數開頭。遞歸解空間樹如下:
? ? ? ? 下面用深搜模板遍歷它。需要記錄哪些信息?三個坑,三個位置,用數組way[N]記錄,遞歸深度u,即當前枚舉哪個位置(第幾個坑)?起始位置start,即當前最小可以從哪枚舉?
【參考代碼】
#include <stdio.h> #define N 30int n, m; int way[N]; // 記錄路徑void dfs(int u, int start) // 當前枚舉的位置u,從start處開始枚舉 {int i;if(u+n-start<m) // 后面的點加起來不足m個,剪枝舍去 return;if(u>m) // 枚舉到葉子結點 {for(i=1;i<=m;i++)printf(" %d",way[i]);printf("\n") ;return;}for(i=start;i<=n;i++) // 從start開始,逐一進行試探 {way[u]=i;dfs(u+1,i+1); // 將i放到u位置,遞歸下一層 ,從i+1開始枚舉} } int main() {scanf("%d%d",&n,&m);dfs(1,1);return 0; }http://ybt.ssoier.cn:8088/problem_show.php?pid=1317
?
新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!總結
以上是生活随笔為你收集整理的信息学奥赛一本通(1317:【例5.2】组合的输出)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信息学奥赛一本通 1059:求平均年龄
- 下一篇: 信息奥赛一本通(1231:最小新整数)