poj3270Cow Sorting(置换+贪心)

Cow Sorting
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 7587   Accepted: 2982

Description

Farmer John's N (1 ≤ N ≤ 10,000) cows are lined up to be milked in the evening. Each cow has a unique "grumpiness" level in the range 1...100,000. Since grumpy cows are more likely to damage FJ's milking equipment, FJ would like to reorder the cows in line so they are lined up in increasing order of grumpiness. During this process, the places of any two cows (not necessarily adjacent) can be interchanged. Since grumpy cows are harder to move, it takes FJ a total of X+Y units of time to exchange two cows whose grumpiness levels are X and Y.

Please help FJ calculate the minimal time required to reorder the cows.

Input

Line 1: A single integer: N
Lines 2..N+1: Each line contains a single integer: line i+1 describes the grumpiness of cow i

Output

Line 1: A single line with the minimal time required to reorder the cows in increasing order of grumpiness.

Sample Input

3
2
3
1

Sample Output

7

Hint

2 3 1 : Initial order. 
2 1 3 : After interchanging cows with grumpiness 3 and 1 (time=1+3=4). 
1 2 3 : After interchanging cows with grumpiness 1 and 2 (time=2+1=3).
/*
* @Author: LyuC
* @Date:   2017-10-12 15:55:54
* @Last Modified by:   LyuC
* @Last Modified time: 2017-10-12 16:52:18
*/
/*
 题意:给你一个无序的序列,让你只能两两进行交换,使得序列有序,每次操作的代价是两个数的和
    问你最少的代价是多少

 思路:置换+贪心
    例子 :
        原始序列:1 8 9 7 6
        排序下标:1 4 5 3 2
            那么我们发现,位置不对的8 9 7 6实际上是一个置换:4->3->5->2->4
        长度为4最少需要交换三次才能使得序列有序,保证了次数最少了,然后就是
        考虑怎么交换才能代价最小,置换(4,3,5,2)可以拆成(2,4),(2,3),(2,5),
        这样就保证了部分交换代价是最小的,但是这个例子就是个特例,如果首先
        将1 6 进行交换使得(4,3,5,1)在一个置换里,交换完再用6把1交换出去,这
        样的代价更小,所以这个有两种最优操作,处理的时候取两者更右者;
*/
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string.h>
#include <algorithm>

#define MAXN 10005
#define INF 0x3f3f3f3f

using namespace std;

struct Node{
    int val;
    int index;
    int sortindex;
}a[MAXN];
int n;
bool vis[MAXN];
vector<int>v[MAXN];
int pos;
int minnum;

bool cmp1(Node a,Node b){
    return a.val<b.val;
}

bool cmp2(Node a,Node b){
    return a.index<b.index;
}

void init(){
    for(int i=0;i<MAXN;i++)
        v[i].clear();
    pos=0;
    minnum=INF;
    memset(vis,false,sizeof vis);
}

int main(){
    // freopen("in.txt","r",stdin);
    while(scanf("%d",&n)!=EOF){
        init();
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i].val);
            a[i].index=i;
            minnum=min(minnum,a[i].val);
        }
        sort(a+1,a+n+1,cmp1);
        for(int i=1;i<=n;i++){
            a[i].sortindex=i;
        }
        sort(a+1,a+n+1,cmp2);
        for(int i=1;i<=n;i++){
            if(vis[i]==true)
                continue;
            int x=i;
            vis[i]=true;
            v[pos].push_back(a[i].sortindex);
            x=a[x].sortindex;
            while(x!=i){
                if(vis[x]==true){
                    break;
                }
                v[pos].push_back(a[x].sortindex);
                vis[x]=true;
                x=a[x].sortindex;
            }
            if(a[x].sortindex==a[i].sortindex){
                pos++;
            }else{
                v[pos].clear();
                v[pos].push_back(i);
                int End=x;
                x=i;
                vis[x]=false;
                while(x!=End){
                    x=a[x].sortindex;
                    vis[x]=false;
                }
                vis[i]=true;
                pos++;
            }
        }
        sort(a+1,a+n+1,cmp1);
        int res=0,ra,rb;
        for(int i=0;i<pos;i++){
            sort(v[i].begin(),v[i].end());
            ra=0;
            for(int j=1;j<(int)v[i].size();j++){
                ra+=(a[v[i][0]].val+a[v[i][j]].val);
            }
            if(minnum!=a[v[i][0]].val){
                rb=0;
                for(int j=1;j<(int)v[i].size();j++){
                    rb+=(minnum+a[v[i][j]].val);
                }
                rb+=2*(minnum+a[v[i][0]].val);
            }else{
                rb=INF;
            }
            res+=min(ra,rb);
        }
        printf("%d\n",res);
    }
    return 0;
}

 

posted @ 2017-10-12 16:53  勿忘初心0924  阅读(168)  评论(0编辑  收藏  举报