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),再把1与0交换(即数字1换到位置1),这样交换的次数才最小。

#pragma comment(linker, "/STACK:102400000, 102400000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define Min(a, b) ((a < b) ? a : b)
#define Max(a, b) ((a < b) ? b : a)
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const double eps = 1e-8;
const int MAXN = 500 + 10;
const int MAXT = 10000 + 10;
using namespace std;
int a[MAXN << 1];
int vis[MAXN];
int solve(int a[], int n){//求最小交换次数
    memset(vis, 0, sizeof vis);
    int cnt = 0;
    for(int i = 0; i < n; ++i){
        if(!vis[i]){
            ++cnt;
            for(int j = i; !vis[j]; j = a[j]) vis[j] = 1;
        }
    }
    return n - cnt;
}
int main(){
    int n;
    while(scanf("%d", &n) == 1){
        if(!n) return 0;
        for(int i = 0; i < n; ++i){
            scanf("%d", &a[i]);
            --a[i];
            a[i + n] = a[i];
        }
        int ans = INT_INF;
        for(int j = 0; j < 2; ++j){//正序反序
            for(int i = 0; i < n; ++i){//枚举起点
                ans = min(ans, solve(a + i, n));
            }
            reverse(a, a + 2 * n);
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

时间: 2024-08-18 19:43:58

UVA - 10570 Meeting with Aliens(外星人聚会)(暴力枚举)的相关文章

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 (暴力)

题意:给定一个排列,每次可交换两个数,用最少的次数把它变成一个1~n的环状排列. 析:暴力题.很容易想到,把所有的情况都算一下,然后再选出次数最少的那一个,也就是说,我们把所有的可能的形成环状排列全算一下,然后选出最少的. 那么就开一个两倍的数组,然后两遍从1到n,然后每次选 n 个,进行暴力,每找一个不同的,就去找这个位置应该放的,然后交换.注意两次正序和逆序暴力. #include <iostream> #include <cmath> #include <cstdlib

UVA - 10570 Meeting with Aliens 暴力

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

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 (置换的循环节)

给出一个长度不超过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 131 The Psychic Poker Player (暴力枚举)

uva 131 The Psychic Poker Player  The Psychic Poker Player  In 5-card draw poker, a player is dealt a hand of five cards (which may be looked at). The player may then discard between zero and five of his or her cards and have them replaced by the sam

UVA - 1262 Password(密码)(暴力枚举)

题意:给两个6行5列的字母矩阵,找出满足如下条件的"密码":密码中的每个字母在两个矩阵的对应列中均出现.给定k(1<=k<=7777),你的任务是找出字典序第k小的密码.如果不存在,输出NO. 分析:因为k<=7777,直接按字典序从小到大的顺序递归一个一个的枚举. 注意:定义在dfs里的vis不能放在全局,否则会导致值的混用. #pragma comment(linker, "/STACK:102400000, 102400000") #incl

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

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

uva 565 - Pizza Anyone?(暴力枚举 + 二进制)

题目:uva 565 - Pizza Anyone?(暴力枚举 + 二进制) 题目大意:题目是说有一个人要帮他的朋友们定批萨,然后每个朋友都有自己的口味要求,问能不能定一个批萨然后满足每个朋友的至少一个要求. 能就输出所定批萨里面加的东西,,输出要求按字典序: 不能就输出:No pizza can satisfy these requests. 解题思路:这题里面有16种材料,每种材料只有取与不取的可能,这样就有 2^16 种( 0 - 2^16 - 1),枚举出每种情况然后在分别看是否能满足每