poj 3270 Cow Sorting

Cow Sorting

题意:有N头牛,每头牛都有不同的暴躁值ai,现在要将所有的牛按照暴躁值从小到大排序,每次交换两个元素(任意交换)时,花费就是两头牛的暴躁值之和;问排序的最小花费为多少?

数据:(1 ≤ N ≤ 10,000) (1 <= ai <= 100,000);

思路:很明显的贪心;(下面讲的循环是置换群里的循环)

策略:我们从没在最终位置且值最小的牛看起,如果每次都是将当前考虑的牛直接与它最终的位置的牛交换,那么这样递推下去,将形成的就是一个循环(一定有牛的最终位置为考虑的起始位置,这是这个循环结束了);

在每一个循环中,由于所有的值都是需要交换的,所以以贪心的思想,每次用最小的牛去交换,值大的牛只交换一次~~,那么这就是循环自己调整的花费的最小值。但是这个策略并没有考虑到用循环外的牛来调整循环里的牛的次序,并且当存在一个循环之外值很小的牛时,用这个牛来调整这个循环里的牛显然花费更低~~;每个循环只需取二者较小的即可;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define MSi(a) memset(a,0x3f,sizeof(a))
#define inf 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1|1
typedef pair<int,int> PII;
#define A first
#define B second
#define MK make_pair
typedef __int64 ll;
template<typename T>
void read1(T &m)
{
    T x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    m = x*f;
}
template<typename T>
void read2(T &a,T &b){read1(a);read1(b);}
template<typename T>
void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
template<typename T>
void out(T a)
{
    if(a>9) out(a/10);
    putchar(a%10+'0');
}
int vis[10010],vec[10010];//没有使用vector,只用一维即可
PII B[10010];
int mn,num;
int solve()
{
    int ans = 0;
    rep0(i,0,num) ans += mn + vec[i];
    ans += vec[0] + mn;
    return ans;
}
int main()
{
    int n,ans = 0,cnt = 0;
    mn = inf;
    read1(n);
    rep1(i,1,n) read1(B[i].A),B[i].B = i,mn = min(mn,B[i].A);
    sort(B+1,B+1+n);
    rep1(i,1,n)if(!vis[i]){
        int tmp = i;
        ++cnt;num = 0;
        do{
            vis[tmp] = 1;
            vec[num++] = B[tmp].A;
            tmp = B[tmp].B;
        }while(!vis[tmp]);
        if(num == 1)   continue;
        sort(vec,vec + num);
        tmp = 0;
        rep0(j,1,num) tmp += vec[j];
        tmp += (num - 1)*vec[0];
        ans += min(tmp,solve());
    }
    printf("%d
",ans);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/hxer/p/5223472.html