pku acm 1833 排列
2012-04-11 16:27
288 查看
这道题目,最直观的想法是求出1到n的所有排列,然后将全部排列排序.
但是,n最大可以是1024,1024!个排 列,几乎永远也算不出来,算出来也没有地方存放。那么,有没有公式或规律,能够很快由一个排列推算出下k个排列呢?
实际上寻找规律或公式都是徒劳的,只能老老实实由给定排列算出下一个排列,再算出下一个排列……一直算到第k的排列。
鉴于k的值很小,最多只有64,因此这种算法应该是可行的。
如何由给定排列求下一个排列?
不妨自己动手做一下。比如:“2 1 4 7 6 3 5”的下一个排列是什么?
容易,显然是“2 1 4 7 6 5 3”,那么,再下一个排列是什么?有点难了,是“2 1 5 3 4 6 7”。
以从“2 1 4 7 6 5 3”求出下一个排列“2 1 5 3 4 6 7”作为例子,可以总结出求给定排列的下一个排列的步骤:
假设给定排列中的n个数从左到右是a1, a2, a3……an。
1)从an开始,往左边找,直到找到某个aj,满足aj-1<aj
(对上例j, 这个aj就是7, aj-1 就是4)。
2)在aj、aj+1…… an中找到最小的比aj-1大的数,将这个数和aj-1互换位置
(对上例, 这个数就是5,和4换完位置后的排列是“2 1 5 7 6 4 3”)。
3)将从位置j到位置n的所有数(共n-j+1个)从小到大重新排序,排好序后,新的排列就是所要求的排列。
(对上例,就是将“7 6 4 3”排序,排好后的新排列就是“2 1 5 3 4 6 7”)。
当然,按照题目要求,如果a1, a2, a3……an已经是降序,那么它的下一个排序就是an, an-1, an-2……a1。
注:上面的是基本思路,但是我们可以根据当前排列的性质,加以优化;
对于第一步,没法优化,只好从后到前找,找到了J。
第二布就可以优化了。循环找是可以,但是从J到J+1是倒序的,这样的话,根据有序的这个特性可以用二分查找,效率由O(n)提到到了O(log(n)).
第三部,排序仍是不需要的,因为从J到J+1是倒序的,只需反转就OK 了,降到了O(n).
接下来粘上代码以供参考
但是,n最大可以是1024,1024!个排 列,几乎永远也算不出来,算出来也没有地方存放。那么,有没有公式或规律,能够很快由一个排列推算出下k个排列呢?
实际上寻找规律或公式都是徒劳的,只能老老实实由给定排列算出下一个排列,再算出下一个排列……一直算到第k的排列。
鉴于k的值很小,最多只有64,因此这种算法应该是可行的。
如何由给定排列求下一个排列?
不妨自己动手做一下。比如:“2 1 4 7 6 3 5”的下一个排列是什么?
容易,显然是“2 1 4 7 6 5 3”,那么,再下一个排列是什么?有点难了,是“2 1 5 3 4 6 7”。
以从“2 1 4 7 6 5 3”求出下一个排列“2 1 5 3 4 6 7”作为例子,可以总结出求给定排列的下一个排列的步骤:
假设给定排列中的n个数从左到右是a1, a2, a3……an。
1)从an开始,往左边找,直到找到某个aj,满足aj-1<aj
(对上例j, 这个aj就是7, aj-1 就是4)。
2)在aj、aj+1…… an中找到最小的比aj-1大的数,将这个数和aj-1互换位置
(对上例, 这个数就是5,和4换完位置后的排列是“2 1 5 7 6 4 3”)。
3)将从位置j到位置n的所有数(共n-j+1个)从小到大重新排序,排好序后,新的排列就是所要求的排列。
(对上例,就是将“7 6 4 3”排序,排好后的新排列就是“2 1 5 3 4 6 7”)。
当然,按照题目要求,如果a1, a2, a3……an已经是降序,那么它的下一个排序就是an, an-1, an-2……a1。
注:上面的是基本思路,但是我们可以根据当前排列的性质,加以优化;
对于第一步,没法优化,只好从后到前找,找到了J。
第二布就可以优化了。循环找是可以,但是从J到J+1是倒序的,这样的话,根据有序的这个特性可以用二分查找,效率由O(n)提到到了O(log(n)).
第三部,排序仍是不需要的,因为从J到J+1是倒序的,只需反转就OK 了,降到了O(n).
接下来粘上代码以供参考
#include<stdio.h> const int N=1015; int str ; int n,k; void restr(int begin) { int end=n-1; int p; while(end>begin) { p=str[end]; str[end]=str[begin]; str[begin]=p; end--; begin++; } } int find(int p,int begin,int end) { if(begin==end)return begin; if(begin+1==end) { if(str[end]>str[p])return end; return begin; } int mid=(begin+end)/2; if(str[mid]<=str[p])return find(p,begin,mid-1); return find(p,mid,end); } void serch(int p) { int p0=find(p-1,p,n-1);//find the first number that is bigger than the value of str[p-1] int p1=str[p-1]; str[p-1]=str[p0]; str[p0]=p1; } void next() { int i=n-1; while(i && str[i-1]>=str[i])i--; if(i==0){restr(0);return ;} serch(i); restr(i); } void print() { printf("%d",str[0]); for(int i=1;i<n;i++) { printf(" %d",str[i]); } printf("\n"); } int main() { scanf("%d",&n); while(scanf("%d%d",&n,&k)!=EOF) { for(int i=0;i<n;i++)scanf("%d",&str[i]); if(n!=1) { while(k--) { next(); } } print(); } return 0; }
相关文章推荐
- pku 1833(排列) STL应用
- PKU 1833 排列
- 排列组合计算第m种组合 STL实现——pku1833
- 初学ACM - 组合数学基础题目PKU 1833
- PKU1833 排列
- pku acm 1833
- pku1833排列
- PKU 1833 排列
- PKU 1833 排列 模似 & 百练1833
- pku1833 排列
- ACM题目分类总结及pku题目分类
- Pku acm 1163 the Triangle
- poj 1833 排列 库函数 next_permutation 的调用
- 1010(stamps),acm.pku.edu.cn
- PKU 2528 POJ 2528 Mayor's posters ( 线段树+离散化 ) ACM 2528 IN PKU
- pku acm 试题分类
- acm pku 1251 Jungle Roads的算法分析与实现
- ACM基本算法分类、推荐学习资料和配套pku习题
- [ACM] hdu 1342 Lotto (排列)
- PKU ACM-1019题 java Number Sequence