nyoj 32-组合数(next_permutation, stack, set)
32-组合数
内存限制:64MB
时间限制:3000ms
Special Judge: No
accepted:8
submit:11
题目描述:
找出从自然数1、2、... 、n(0<n<10)中任取r(0<r<=n)个数的所有组合。
输入描述:
输入n、r。
输出描述:
按特定顺序输出所有组合。 特定顺序:每一个组合中的值从大到小排列,组合之间按逆字典序排列。
样例输入:
5 3
样例输出:
543 542 541 532 531 521 432 431 421 321
分析:
①、要求从n个元素中选m个元素,其实就是从全排列中选择它的前m项就行了;
②、因为本题对顺序做了限制,所以我们还要将选出的元素排序、去重;
步骤:
①、首先来说,我们要产生一组全排列,这里我们通过STl中的next_permutation
②、将每个全排列前m项取出,排序后插入set(PS:set具有去重的功能)
③、将从set取出的每一个值依次放入栈(stack)中(利用栈的“先进后出”)
④、从栈(stack)中取出、输出
核心代码:
1 do 2 { 3 if(!equal(A, A + m, temp)) // 解释:如果数组A的前m个元素与temp两个数组不相等 4 { 5 for(int i = 0; i < m; ++ i) 6 temp2[i] = temp[i] = A[i]; 7 sort(temp2, temp2 + m, greater<int>()); 8 string s; 9 for(int i = 0; i < m; ++ i) 10 s += char('0' + temp2[i]); 11 my_set.insert(s); 12 } 13 } 14 while(next_permutation(A, A + n));
C/C++代码实现(AC):
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 #include <stack> 7 #include <map> 8 #include <queue> 9 #include <set> 10 11 using namespace std; 12 const int MAXN = 12; 13 int A[MAXN]; 14 15 void cal_array(int n) 16 { 17 for(int i = 0; i < n; ++ i) 18 A[i] = i + 1; 19 } 20 21 int main() 22 { 23 24 int n, m, temp[MAXN] = {0}, temp2[MAXN] = {0}; 25 scanf("%d%d", &n, &m); 26 set <string> my_set; 27 set <string> ::iterator iter; 28 stack <string> my_stack; 29 cal_array(n); 30 do 31 { 32 if(!equal(A, A + m, temp)) // 解释:如果数组A的前m个元素与temp两个数组不相等 33 { 34 for(int i = 0; i < m; ++ i) 35 temp2[i] = temp[i] = A[i]; 36 sort(temp2, temp2 + m, greater<int>()); 37 string s; 38 for(int i = 0; i < m; ++ i) 39 s += char('0' + temp2[i]); 40 my_set.insert(s); 41 } 42 } 43 while(next_permutation(A, A + n)); 44 45 for(iter = my_set.begin(); iter != my_set.end(); ++ iter) 46 my_stack.push(*iter); 47 while(!my_stack.empty()) 48 { 49 cout <<my_stack.top() <<endl;; 50 my_stack.pop(); 51 } 52 return 0; 53 }