UVa 10570 Meeting with Aliens (暴力)

题意:给定一个排列,每次可交换两个数,用最少的次数把它变成一个1~n的环状排列。

析:暴力题。很容易想到,把所有的情况都算一下,然后再选出次数最少的那一个,也就是说,我们把所有的可能的形成环状排列全算一下,然后选出最少的。

那么就开一个两倍的数组,然后两遍从1到n,然后每次选 n 个,进行暴力,每找一个不同的,就去找这个位置应该放的,然后交换。注意两次正序和逆序暴力。

#include <iostream>
#include <cmath>
#include <cstdlib>
#include <set>
#include <cstdio>
#include <cstring>

using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 500 + 5;
int a[maxn], b[maxn<<1], c[maxn], d[maxn<<1];

int main(){
    int n;
    while(scanf("%d", &n) == 1 && n){
        int ans = INF;
        for(int i = 0; i < n; ++i){  scanf("%d", a+i); b[i] = i+1; }
        memcpy(b+n, b, sizeof(int)*n);
        memcpy(c, a, sizeof(a));

        for(int k = 0; k < n; ++k){
            int cnt = 0;
            memcpy(a, c, sizeof(a));

            for(int i = 0, j = k; i < n && cnt < ans; ++j, ++i){
                if(a[i] == b[j])  continue;
                for(int l = i+1; l < n; ++l) if(b[j] == a[l]){
                    a[l] = a[i];
                    a[i] = b[j];
                    break;
                }
                ++cnt;
            }
            ans = min(ans, cnt);
        }

        for(int i = 0; i < n; ++i)  d[i] = n-i;
        memcpy(d+n, d, sizeof(int)*n);
        for(int k = 0; k < n; ++k){
            int cnt = 0;
            memcpy(a, c, sizeof(a));
            for(int i = 0, j = k; i < n && cnt < ans; ++j, ++i){
                if(a[i] == d[j])  continue;
                for(int l = i+1; l < n; ++l) if(d[j] == a[l]){
                    a[l] = a[i];
                    a[i] = d[j];
                    break;
                }
                ++cnt;
            }
            ans = min(ans, cnt);
        }
        printf("%d\n", ans);
    }
    return 0;
}

代码如下:

时间: 2024-12-24 08:05:24

UVa 10570 Meeting with Aliens (暴力)的相关文章

UVA - 10570 Meeting with Aliens 暴力

题目大意:有n个外星人要开园桌会议,外星人的编号由1到n,要求编号为i的外星人的相邻位置必须坐着编号为i-1和编号为i+1的外星人. 现在给出n个外星人坐在圆桌上的顺序,要求你经过最少次交换(交换是两个外星人交换所坐位置),使得所有外星人坐法都符合上诉规则. 解题思路:枚举每个外星人坐的位置,假设该位置坐的必须是编号为1的外星人,然后编号从左递增或者递减,最后检查该安排需要交换几次外星人 如果该外星人坐的位置是错的话,就直接把适合坐该座位的外星人何其交换过来,这样的交换次数是最少的 #inclu

UVA - 10570 Meeting with Aliens(外星人聚会)(暴力枚举)

题意:输入1~n的一个排列(3<=n<=500),每次可以交换两个整数.用最少的交换次数把排列变成1~n的一个环状序列. 分析:正序反序皆可.枚举每一个起点,求最少交换次数,取最小值. 求最小交换次数solve函数,将所有不需要交换的数字用cnt统计出来,而需要交换的数字集合(个数为n)交换次数是n-1,统计一次cnt. 原因:如序列3 1 2 5 6 4,因为下标从0开始,因此将序列变为2 0 1 4 5 3,假设求以2为起点的序列正序最小交换次数,是先将2与1交换(即数字2换到位置2),再

UVA 10570 Meeting with Aliens

#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1<<29; int n,a[maxn]; int a1[maxn],id1[maxn]; int a2[maxn

UVA 10570 Meeting with Aliens 外星人聚会

题意:给你一个排列,每次可以交换两个整数(不一定要相邻),求最少交换次数把排列变成一个1~n的环形排列.(正反都算) 其实就是找环了,对于一个链状序列,最小交换次数等于不在对应位置的数字个数减去环的个数. 至于证明这里讲的比较详细:http://www.dewen.io/q/7967#ans16319 所以只要枚举一下环的起点就好了,dfs找环就行了. #include<bits/stdc++.h> using namespace std; const int maxn = 1e3+233;

UVA - 10570 Meeting with Aliens (置换的循环节)

给出一个长度不超过500的环状排列,每次操作可以交换任意两个数,求把这个排列变成有序的环状排列所需的最小操作次数. 首先把环状排列的起点固定使其成为链状排列a,枚举排好序时的状态b(一种有2n种可能),则b可以看成是原状态a的一个置换,把a变为b所需的最小交换次数即为a的长度n减去置换循环节的数量. 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 typedef long long ll; 5 const int N=500+10; 6

【uva 10570】Meeting with Aliens(算法效率--暴力+贪心)

题意:输入1~N的一个排列,每次可以交换2个整数,问使排列变成1~N的一个环状排列所需的虽少交换次数.(3≤N≤500) 解法:(又是一道我没打代码,光想和看就花了很久时间的题~QwQ)由于n很小,可以暴力枚举目标的环状排列,于是贪心交换——把元素 x 直接与它的目标位置上的元素互换,这样至少使1个元素的位置正确了.而若 x 先与其他 k 个元素交换,是最多能得到 k+1 个元素的正确排列的,这样并没有之前的策略优.    另外,网上关于此题还有一种关于对链状序列找环的说法,我更加不理解.若有人

【UVA】12169-Disgruntled Judge(暴力or欧几里得)

可能由于后台数据的原因,这道题直接暴力枚举a,b进行判断也能过,不过跑的时间长,效率太差了. 14021006 12169 Disgruntled Judge Accepted C++ 0.876 2014-08-11 08:46:28 不说了,比较无脑. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #incl

uva 10825 - Anagram and Multiplication(暴力)

题目链接:uva 10825 - Anagram and Multiplication 题目大意:给出m和n,要求找一个m位的n进制数,要求说该数乘以2~m中的任意一个数的结果是原先数各个位上数值的一个排序. 解题思路:枚举最后一位数,然后用这个数去乘以2~m并对n取模,然后得到的数一定就是这个数的组成,暴力搜索一下并判断. #include <cstdio> #include <cstring> #include <algorithm> using namespace

uva 11256 - Repetitive Multiple(gcd+暴力)

题目链接:uva 11256 - Repetitive Multiple 题目大意:给定一个数n,要求找到最小的k,使得k?n为题目中定义的重复数字. 解题思路:枚举k?n的循环节长度,比如当前枚举为2,那么一次判断u=1001,1001001,1001001001 ...,取d = gcd(n,u), 那么k = u / d, a = n / d (因为n?k=u?a)并且保证a的长度为2,所以k和a要同时扩大相应倍数.枚举过程中为何k. #include <cstdio> #include