UVa 11925 Generating Permutations (构造法)

题意:给定一个序列,让你从一个升序列变成该序列,并且只有两种操作,操作1:交换前两个元素,操作2:把第一个元素移动到最后。

析:一开始的时候吧,不会,还是看的题解,首先是要逆序来做,这样可能好做一点,那么操作1不变,操作2变成把最后一个元素放到最前面。

就像是冒泡排序一样,如果第一个元素大于第二个,交换顺序,否则就把最后一个元素移动到最前面,但第三个样例就死循环了,我也算过,这样会一直重复某几个状态,

所以我们要维护第一个值,如果是最大的元素,那么就不让他们交换了。

代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <iterator>

using namespace std;
const int maxn = 300 + 5;
vector<int> ans, a;
int n;

bool judge(){
    for(int i = 0; i < n; ++i)
        if(a[i] != i+1)  return false;
    return true;
}

int main(){
    int x;
//    freopen("in.txt", "r", stdin);
    while(scanf("%d", &n) == 1 && n){
        ans.clear();
        a.clear();
        for(int i = 0; i < n; ++i){ scanf("%d", &x);  a.push_back(x);  }

        if(1 == n){  puts("");  continue;  }
        while(true){
            if(judge())  break;
            if(a[0] > a[1] && a[0] != n){
                swap(a[0], a[1]);
                ans.push_back(1);
            }
            else{
                a.insert(a.begin(), a[n-1]);
                a.resize(n);
                ans.push_back(2);
            }
        }

        for(int i = ans.size()-1; i >= 0; --i)
            printf("%d", ans[i]);
        printf("\n");
    }
    return 0;
}
时间: 2024-12-27 00:29:29

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 推理

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

UVA 11925 Generating Permutations 生成排列

题意:要用一个有序的序列生成给定序列,操作有两种,一是交换前两个元素,二是把第一个元素移动到最后去. 思路有两种: 1.映射,把给定序列映射成有序的序列,然后按照同样的替换规则把有序的序列映射掉,然后就可以排序啦. 具体解释可以看SRM 664的C题 2.逆向思考,把给定序列变成有序,操作相应变化一下,最后逆序输出操作. 至于排序的问题,把序列看成一个环,第二种操作相当改变了可交换元素的位置,然后就可以等效为冒泡排序啦... 第二种思路需要注意的一点是,是因为是环状的,和冒泡排序有所区别,最大的

利用子集构造法实现NFA到DFA的转换

概述 NFA非有穷自动机,即当前状态识别某个转换条件后到达的后继状态不唯一,这种自动机不便机械实现,而DFA是确定有限状态的自动机,它的状态转换的条件是确定的,且状态数目往往少于NFA,所以DFA能够比较方便的机械实现且识别能力方面也和NFA相当.本次实验采用子集构造法来实现不带空弧的由NFA到DFA的转换. 子集构造法的算法如下: 设NFA为M=(K,Σ,f,S0,Z),则构造相应的DFA  M′=(Q,Σ,f′,I0,F)①取I0=S0:②对于状态集Q中任一尚未标记的状态qi={Si1,Si

生成子集 (增量构造法)

使用增量构造法可以构造出升序数组arr的不重复子集,并且按字典序排序 #include<bits/stdc++.h> using namespace std; int arr[16]; inline void print_subset(int *index, int cur, int n)///cur值这里可以理解为在这个堆栈层子集的集合数 { for(int i=0; i<cur; i++) {printf("%d ", arr[index[i]]);} if(cu

【算法竞赛入门经典】7.3子集生成【增量构造法】【位向量法】【二进制法】

7.3.1增量构造法 思路:一次选出一个元素放到集合中.自己对于递归的理解还是不够,这里虽然没有明确给出递归停止条件,但是如果无法继续添加元素,就不会再继续递归,然后就是我头疼的回溯啦. #include<stdio.h> int num[4],n; void A(int n,int *a,int ans) { for(int i = 0; i < ans; i ++)//打印当前元素 printf("%d ",a[i]); printf("\n"

uva 269 - Counting Patterns(构造)

题目链接:uva 269 - Counting Patterns 题目大意:给出n和k,要求找出满足的序列,要求为n元组,由-k到k组成,并且和为0.求出所有满足的元组个数,并且对于左移,右移,水平翻转,每个元素取相反数相同的视为一种,用字典序最大的表示,输出按照字典序最小的输出. 解题思路:因为表示的时候按照字典序最大的表示,一开始枚举开头的位置,那么在后面的数的绝对值就不会大于该数.最后判断一下,如果该序列不是最优的表示方法,就不是该情况. #include <cstdio> #inclu

子集生成——增量构造法+位向量法+二进制法

1.增量构造法: 原理图: 1 // 此算法仅用于输出下标,实际运用应输入另一个数组来进行数据的储存 2 #include <bits/stdc++.h> 3 using namespace std; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define INF 0X3f3f3f3f 7 const ll MAXN = 1e3 + 7; 8 const ll MOD = 1e9 + 7; 9 int a[10];

(白书训练计划)UVa 1605 Building for UN(构造法)

题目地址:UVa 1605 一道答案特判的题.最简单的方法是只构造两层,第一层中第i行全是i国家,第二层中第i列全是i国家.这样就保证了所有的国家都会相邻. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h&