UVA 11925 Generating Permutations 生成排列

题意:要用一个有序的序列生成给定序列,操作有两种,一是交换前两个元素,二是把第一个元素移动到最后去。

思路有两种:

1.映射,把给定序列映射成有序的序列,然后按照同样的替换规则把有序的序列映射掉,然后就可以排序啦。

具体解释可以看SRM 664的C题

2.逆向思考,把给定序列变成有序,操作相应变化一下,最后逆序输出操作。

至于排序的问题,把序列看成一个环,第二种操作相当改变了可交换元素的位置,然后就可以等效为冒泡排序啦。。。

第二种思路需要注意的一点是,是因为是环状的,和冒泡排序有所区别,最大的元素在头部的时候不能进行交换了,否则陷入死循环,最大的元素所在的位置相当与链状时候的最后面的有序区,是不需要比较的。

判断终止可以先求出逆序对总数,交换一次逆序数减一

#include<bits/stdc++.h>
using namespace std;

int a[360],t[360],inv;

void merge_sort(int l,int r)
{
    if(l == r) return;
    int mid = (l+r) >> 1;
    merge_sort(l,mid);
    merge_sort(mid+1,r);
    int p = l, q = r, k = l;
    while(p <= mid && q <= r){
        if(a[p]>a[q]) {
            inv += mid - p + 1;
            t[k++] = a[q++];
        } else {
            t[k++] = a[p++];
        }
    }
    if(p>mid) for(int i = q; i <= r; i++) t[k++] = a[i];
    else for(int i = q; i <= mid; i++) t[k++] = a[i];
    for(k = l; k <= r; k++) a[k] = t[k];
}

int main()
{
    //freopen("in.txt","r",stdin);
    int n, b[360];
    while(scanf("%d",&n),n){
        for(int i = 0; i < n; i++) {
            int t; scanf("%d",&t);
            b[t-1] = i;
        }

        memcpy(a,b,sizeof(int)*n);
        inv = 0;
        merge_sort(0,n-1);

        for(int i = n-1; i >= 1 && inv ; i--){
            for(int j = 0; j < i; j++){
                if( b[j] > b[j+1]) {
                    swap(b[j],b[j+1]);
                    putchar(‘1‘);
                    inv--;
                }
                putchar(‘2‘);
            }
            //continue move i -> 1
            for(int j = i; j < n ;j++){
                putchar(‘2‘);
            }
        }

        putchar(‘\n‘);
    }
    return 0;
}
时间: 2024-10-05 05:01:46

UVA 11925 Generating Permutations 生成排列的相关文章

uva 11925 Generating Permutations

题意: 给定一到n的序列,按照下列规则,将序列排为升序列 1.交换前两个数 2.将最后一个数放在最前面(紫书错了,害惨我了) 数据量为300,刘汝佳提示是最多2*n*n次操作,所以我选择了数组模拟,正常数组无法将最后一个放到前面,所以我将数组倒置 因为没有要求最优解,只要能得到想要的结果就行了,所以采取了构造法 只要在第一个比第二个小,那么就把最后一个放到最前面,否则就交换前两个,这样就可以把大的慢慢往后放,如果n 1的情况,那么就要把最后一个放到最后面,不然就会陷入循环 例如4 2 3 1  

UVa 11925 Generating Permutations (构造法)

题意:给定一个序列,让你从一个升序列变成该序列,并且只有两种操作,操作1:交换前两个元素,操作2:把第一个元素移动到最后. 析:一开始的时候吧,不会,还是看的题解,首先是要逆序来做,这样可能好做一点,那么操作1不变,操作2变成把最后一个元素放到最前面. 就像是冒泡排序一样,如果第一个元素大于第二个,交换顺序,否则就把最后一个元素移动到最前面,但第三个样例就死循环了,我也算过,这样会一直重复某几个状态, 所以我们要维护第一个值,如果是最大的元素,那么就不让他们交换了. 代码如下: #include

UVA - 11925 Generating Permutations 推理

题目大意:这题的题目是错的,他的第二个操作是把最后一个调到第一个,然后输出时要逆序输出 解题思路:类似冒泡排序法.先如果第一个是n的话,就调后面的到前面来,然后进行比较,取最大的放前面,这下下一次n到前面的时候,n-1就在n的后面了. #include<cstdio> #include<vector> #include<deque> #define maxn 310 using namespace std; int num[maxn], n; deque<int&

减一技术应用:生成排列与幂集(Java实现)

减一技术,与二分搜索一样,是一种通用算法设计技术.它是分治法的一种特殊形式,通过建立问题实例P(n) 与问题实例P(n-1)的递推求解关系式而实现:最经典的例子莫过于插入排序了.这里,给出减一技术在生成排列组合方面的应用. (一)  排列问题: 生成自然数 1,2,,,,,n 的所有排列. 算法描述: 使用减一技术,建立自然数12...n的排列与12...n-1的递推关系.假设 P(n-1) 是 自然数 12...n-1的所有排列 p1, p2,..., p(m)的集合,则P(n)通过如下方式得

HDU 4771 Stealing Harry Potter&#39;s Precious (生成排列+枚举 + BFS)

Stealing Harry Potter's Precious Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1982    Accepted Submission(s): 931 Problem Description Harry Potter has some precious. For example, his invisib

生成排列的递归方法

一  提议描述: 输入正整数n,按照字典序从小到大的顺序输出前n个数的所有排列. 二 思路分析: 对此问题用递归的思想解决:先输出所有以1开头的排列(递归调用),然后输出以2开头的排列(递归调用),接着以3开头的排列,„,最后才是以n开头的排列. 以1开头的排列的特点是:第一位是1,后面是按字典序的2-9的排列.所以在设计递归函数需要以下参数: (1)已经确定的“前缀”序列,以便输出: (2)需要进行全排列的元素集合,以便依次选做第一个元素. 这样,写出以下的伪代码: void print_pe

算法笔记03--归纳法之生成排列

生成排列 生成排列即对n个数的全排列,显然时间复杂度是n指数级的O(n^k) 假定可以生成n-1个数的所有排列,那么就可以扩展生成1,2,.....,n的排列. 例如1的生成排列即1 1,2的生成排列即1,2和2,1 1,2,3的生成排列在1,2的生成排列基础上可以这样得到: 1在第1位,2,3的生成排列 2在第1位,1,3的生成排列 3在第1位,2,3的生成排列 那么推广到1,2,...,n的生成排列即: 1在第1位,2,...,n的生成排列 2在第2位,1,3,...n的生成排列 ....

UVA - 10098 - Generating Fast (枚举排列)

思路:生成全排列,用next_permutation,注意生成之前先对那个字符数组排序. AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; char str[20]; int main() { int n; cin >> n; while(n-

python 生成排列、组合以及选择

from <python cookbook> 19.15 任务 需要对一个序列的排列(permutation).组合(combination)或选择(selection)进行迭代操作.即使初始的序列长度并不长,组合计算的规则却显示生成的序列可能非常庞大,比如一个长度为13的序列有超过60亿种可能的排列.所以,你肯定不希望在开始迭代前计算并生成序列中的所有项 解决方案 生成器允许你在迭代的时候一次一个的计算需要的对象.如果有很多这种对象,而且你也必须逐个的检查他们,那么程序无可避免的会用很长时间