PKU 1833 排列 模似 & 百练1833
2010-11-25 20:07
211 查看
求当前排列的下K个排列:
(1):当当前排列为逆序排列时(最后一个排列), 下一个排列为:1 2 3 4 ....N
(2):下K次排列, 每次改变一次排列, 要考虑(1)
(3):要得到下一次排列, 从An开始, 当Ai > Ai-1时, 将Ai ~An从小到大排序, 在Ai ~ An中找出第一个大于Ai-1的数,
交换, 再将Ai ~ An从小到大排序就得到相应的下一个排列。
用include <algorithm>中的next_permutation(), 也可以很快求出排列
交换时用第0号元素当中间变量, 实现交换, 不知怎么的当时交换的方式乱七八糟的, 就错了几次....唉
Accepted 144K 547MS C 2115B 2010-11-25 19:53:32
代码
/*问题描述大家知道,给出正整数n,则1 到n 这n 个数可以构成n!种排列,把这些排列按照从小到大的顺序
(字典顺序)列出,如n=3 时,列出1 2 3,1 3 2,2 1 3,2 3 1,3 1 2,3 2 1六个排列。给出某个排列,
求出这个排列的下k 个排列,如果遇到最后一个排列,则下1 排列为第1 个排列,即排列1 2 3…n。
比如:n = 3,k=2 给出排列2 3 1,则它的下1 个排列为3 1 2,下2 个排列为3 2 1,因此答案为3 2 1。
输入数据第一行是一个正整数m,表示测试数据的个数,下面是m 组测试数据,每组测试数据第一行是2 个正整数n
( 1 <= n < 1024 )和k(1<=k<=64),第二行有n 个正整数,是1,2 … n的一个排列。
输出要求对于每组输入数据,输出一行,n 个数,中间用空格隔开,表示输入排列的下k 个排列。
输入样例33 12 3 13 13 2 110 21 2 3 4 5 6 7 8 9 10
输出样例3 1 21 2 31 2 3 4 5 6 7 9 8 10*/
(1):当当前排列为逆序排列时(最后一个排列), 下一个排列为:1 2 3 4 ....N
(2):下K次排列, 每次改变一次排列, 要考虑(1)
(3):要得到下一次排列, 从An开始, 当Ai > Ai-1时, 将Ai ~An从小到大排序, 在Ai ~ An中找出第一个大于Ai-1的数,
交换, 再将Ai ~ An从小到大排序就得到相应的下一个排列。
用include <algorithm>中的next_permutation(), 也可以很快求出排列
交换时用第0号元素当中间变量, 实现交换, 不知怎么的当时交换的方式乱七八糟的, 就错了几次....唉
Accepted 144K 547MS C 2115B 2010-11-25 19:53:32
代码
#include <stdio.h> #include <stdlib.h> /* 判断是否是最后一个排列 */ char is_last_per(int *num, int n) { int i; for (i = 1; i < n; i++) { if (num[i] > num[i+1]) { continue; } else { return '0'; } } return '1'; } /* 快速排序 */ void quick_sort(int *num, int *begin , int *end) { int *i, *j; if (end - begin <= 1) { return; } i = begin; j = end - 1; num[0] = *begin; while (i < j) { while (i < j && num[0] <= *j) { j--; } if (i < j) { *i = *j; i++; } while (i < j && num[0] >= *i) { i++; } if (i < j) { *j = *i; j--; } } *j = num[0]; quick_sort(num, begin, j); /* 左边 */ quick_sort(num, j + 1, end); /* 右边 */ } /* 输出 */ void print(int *num, int n) { int i; for (i = 1; i <= n; i++) { printf("%d", num[i]); if (i != n) { putchar(' '); } else { putchar('\n'); } } } /* 设置下一个排列 */ void set_per(int *num, int n) { int i, j; char is_last; /* 判断是否是最后一个排列 */ is_last = is_last_per(num, n); if (is_last == '1') /* 不是最后一个排列 */ { for (i = 1; i <= n; i++) { num[i] = i; } } else { for (i = n; i > 1; i--) { if (num[i] > num[i-1]) { quick_sort(num, &num[i], &num[n+1]); /* 一共两次排序 */ for (j = i; j <= n; j++) { if (num[i-1] > num[j]) { continue; } else /* 交换 */ { num[0] = num[i-1]; num[i-1] = num[j]; num[j] = num[0]; break; } } quick_sort(num, &num[i], &num[n+1]); /* 一共两次排序 */ return; } else { continue; } } } } /* 第k个排列 */ void k_permutation(int num[], int n, int k) { while ( k-- ) /* k次排列, 每次改变一次 */ { set_per(num, n); /* 设置下一个排列 */ } } int main() { int cas, n, k, i, *num; scanf("%d", &cas); while ( cas-- ) { scanf("%d%d", &n, &k); if ((num=(int *) calloc (n + 1, sizeof(int))) == NULL) { printf("空间分配失败!\n"); exit(-1); } for (i = 1; i <= n; i++) { scanf("%d", &num[i]); } k_permutation(num, n, k); /* 下k个排列后 */ print(num, n); free( num ); num = NULL; } }
/*问题描述大家知道,给出正整数n,则1 到n 这n 个数可以构成n!种排列,把这些排列按照从小到大的顺序
(字典顺序)列出,如n=3 时,列出1 2 3,1 3 2,2 1 3,2 3 1,3 1 2,3 2 1六个排列。给出某个排列,
求出这个排列的下k 个排列,如果遇到最后一个排列,则下1 排列为第1 个排列,即排列1 2 3…n。
比如:n = 3,k=2 给出排列2 3 1,则它的下1 个排列为3 1 2,下2 个排列为3 2 1,因此答案为3 2 1。
输入数据第一行是一个正整数m,表示测试数据的个数,下面是m 组测试数据,每组测试数据第一行是2 个正整数n
( 1 <= n < 1024 )和k(1<=k<=64),第二行有n 个正整数,是1,2 … n的一个排列。
输出要求对于每组输入数据,输出一行,n 个数,中间用空格隔开,表示输入排列的下k 个排列。
输入样例33 12 3 13 13 2 110 21 2 3 4 5 6 7 8 9 10
输出样例3 1 21 2 31 2 3 4 5 6 7 9 8 10*/
相关文章推荐
- PKU 1833 排列
- PKU 1833 排列
- PKU1833 排列
- pku1833 排列
- pku acm 1833 排列
- 排列组合计算第m种组合 STL实现——pku1833
- pku1833排列
- pku 1833(排列) STL应用
- pku2342&&pku1463&&pku1947
- 初学ACM - 组合数学基础题目PKU 1833
- UESTC 1214 divide && PKU 3390 Print Words in Lines [DP]
- stl 生成排列 && 标准IO的限定加速
- Poj 1833 排列 —— 一道水题的凌乱
- poj 1833 排列
- POJ1833 排列
- poj 1833 排列
- poj 1833 排列
- 输入一个字符串,要求输出字符串中字符所有的排列,例如输入"abc",得到"abc","acb","bca","bac","cab","cba"
- 字符串排列组合问题&递归算法(1)
- POJ/PKU 2429 GCD & LCM