首页 > 其他 > 详细

UVA 10570 Meeting with Aliens 外星人聚会

时间:2015-08-10 01:37:37      阅读:218      评论:0      收藏:0      [点我收藏+]

题意:给你一个排列,每次可以交换两个整数(不一定要相邻),求最少交换次数把排列变成一个1~n的环形排列。(正反都算)

其实就是找环了,对于一个链状序列,最小交换次数等于不在对应位置的数字个数减去环的个数。

至于证明这里讲的比较详细:http://www.dewen.io/q/7967#ans16319

所以只要枚举一下环的起点就好了,dfs找环就行了。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3+233;
#define bug(x) cout<<#x<<‘=‘<<x<<endl;
int a[maxn];

bool vis[maxn];

int cnt,s;
void dfs(int u)
{
    if(vis[u]) return;
    cnt++;
    vis[u] = true;
    dfs(a[u+s]);
}
int n;

void dfs2(int u)
{
    if(vis[n-1-u]) return;
    cnt++;
    vis[n-1-u] = true;
    dfs2(a[n-1-u+s]);
}

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

        int ans = INT_MAX;
        for( s = 0; s < n; s++){
            int cur = 0;
            memset(vis,0,sizeof(vis));
            for(int i = 0; i < n; i++)if(!vis[i]) {
                if(a[i+s] != i) {
                    vis[i] = true; cnt = 0;
                    dfs(a[i+s]);
                    cur += cnt;
                }else vis[i] = true;
            }
            ans = min(ans,cur);
        }
        reverse(a,a+2*n);
        for( s = 0; s < n; s++){
            int cur = 0;
            memset(vis,0,sizeof(vis));
            for(int i = 0; i < n; i++)if(!vis[i]) {
                if(a[i+s] != i) {
                    vis[i] = true; cnt = 0;
                    dfs(a[i+s]);
                    cur += cnt;
                }else vis[i] = true;
            }
            ans = min(ans,cur);
        }

        printf("%d\n",ans);
    }
    return 0;
}

 

UVA 10570 Meeting with Aliens 外星人聚会

原文:http://www.cnblogs.com/jerryRey/p/4716832.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!