#题解 组合的输出

读题!ヾ(*ΦωΦ)ツ

题目描述

排列与组合是常用的数学方法,其中组合就是从nn个元素中抽出rr个元素(不分顺序且rnr \le n),我们可以简单地将nn个元素理解为自然数1,2,,n1,2,…,n从中任取r个数。

现要求你输出所有组合。

例如n=5,r=3n=5,r=3,所有组合为:

123,124,125,134,135,145,234,235,245,34512 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,0rn)n,r(1<n<21,0 \le r \le n)

输出格式

所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素占三个字符的位置,所有的组合也按字典顺序。
注意哦!输出时,每个数字需要3个场宽

输入输出样例

输入 #1复制

5 3

输出 #1复制

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选n,他这却是n选r,也好实现,多加一个变量就可以;上道题123、132、213、231、312、321是不同方法,此题却是一种方法,这就是我们最大的拦路虎。
别急,按照套路来,分析样例!!!
emm……看上去没啥规律,但我们找到了他们的共同点:后一个数总比前一个数大,前一个数不就是ans的第done项吗,比他大不就是加一吗?思路有了,开始码代码吧!
这是上一题的代码:

#include<bits/stdc++.h>//万能头文件 
using namespace std;
int ans[25]={0},n;
int flag[25] = {1};
void rank(int done){//全排列 
	if(done==n){
		
		for(int i = 0; i < n; i++){
			cout << setw(5) << ans[i]; 
		}
		cout << endl;
		return;
	}
	for(int i = 1; i <= n; i++){
		if(flag[i] == 0){
			flag[i] = 1;
			ans[done]=i;
			rank(done+1);
			flag[i] = 0;
		}
	}
} 
int main(int argc, char** argv) {
	cin >> n;
	rank(0);
	return 0;
}

首先最上面的变量数组,去掉flag(后面的比前面的大当然不会重复咯),加上r:

int ans[100]={0},r,n;

接下来把终止条件改一下,改成r==done,setw(5),代码:

if(r==done){
	for(int i = 1; i <= r; i++){
		cout << setw(3) << ans[i]; 
	}
	cout << endl;
	return ;
}

最后,再把for循环i的值更改一下,if语句和flag赋值去掉。

for(int i = ans[done] + 1; i <= n; i++){
		ans[done+1] = i; 
		rank(done+1);
}

函数搞定!
再把主函数改一下:

int main(int argc, char** argv) {
	cin >> n >> r;
	rank(0);
	return 0;
}

完整代码

请勿抄袭!

#include<bits/stdc++.h>//万能头文件 
#include <iostream>
#include <cstring>
#include <algorithm>   
#include <math.h>
#include <cstdio>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int ans[100]={0},r,n;
void rank(int done){//全排列 
	if(r==done){
		for(int i = 1; i <= r; i++){
			cout << setw(3) << ans[i]; 
		}
		cout << endl;
		return ;
	}
	for(int i = ans[done] + 1; i <= n; i++){
			ans[done+1] = i; 
			rank(done+1);
	}
} 
int main(int argc, char** argv) {
	cin >> n >> r;
	rank(0);
	return 0;
}
你通过了此题——恭喜!