POJ3270 Cow Sorting【置换群】【间接排序】

来源:互联网 发布:帝国时代2日本武士数据 编辑:程序博客网 时间:2024/06/04 18:05
题目链接:
http://poj.org/problem?id=3270

题目大意:

有N头牛,每头牛都有一个脾气值(唯一),给你N头牛的脾气值序列,可以通过交换任意

两头牛的位置,直到脾气值序列为升序,但是交换 Cow[i] 和 Cow[j] 的代价是 Cow[i] + 

Cow[j]。

问:求出将N头牛的脾气值变成升序排列所需要花费的最小代价


解题思路:

贪心思想:每次交换,我们总是希望脾气最低的那头牛与其他牛参与交换(置换),这样不断

的两两置换,由于没有重复的脾气值,则置换过程中必然会产生一个循环,这些循环构成了

一个个的置换群,对于每一个置换群,根据贪心思想:我们有两种方法交换使代价最小。

第一种:找到每个置换群里脾气最小的牛,让它和其他牛进行置换,花费代价为

Sum1 = Sum - Mina + (len-1)*Mina //化简为 Sum + (len-2)*Mina

//Sum 为置换群中所有牛的脾气和,len 为置换群的元素个数,Mina 为置换群里脾气最小

第二种:从整个牛的序列中找到脾气最小的牛,让它和置换群里的牛进行置换,最后再将置

群里脾气最小的牛 Mina 和整个序列中脾气最小的牛进行置换,花费代价为

Sum2 = Sum + Mina + (len+1)*Min;

//Sum 为置换群中所有牛的脾气,Mina为置换群中脾气最小的牛,len为置换群的元素个数,

Min 为整个序列中脾气最小的牛

比较两种情况的代价,结果加上代价小的代价值。

注:代码中用到了间接排序, 即除了 Cow[] 数组外,另开一个数组 CowNo[] 数组,初始化

小标对 CowNo[] 按照 Cow[] 数组的值升序排列,则 CowNo[] 中存放的是 Cow[] 数组第 i

个元素在整个 Cow[] 数组中是第几小的数。

比如

Cow[5]       =   2 5 7 6 4

CowNo[5]  =   1 3 5 4 2 

CowNo[2] = 3 表示 Cow[2] 在整个 Cow[] 数组中排第二小

间接排序可以在不改变原数组顺序的情况下,得到原数组的排列顺序,比较方便。


AC代码:

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int INF = 0xffffff0;int Cow[100100],CowNo[100100],Vis[100100];int cmp(const int a,const int b)//间接排序的关键{    return Cow[a] < Cow[b];}int main(){    int n,Min,res;    while(~scanf("%d",&n))    {        memset(Cow,0,sizeof(Cow));        memset(CowNo,0,sizeof(CowNo));        memset(Vis,0,sizeof(Vis));        for(int i = 1; i <= n; i++)            scanf("%d",&Cow[i]);        Min = INF;        for(int i = 1; i <= n; i++)            if(Cow[i] < Min)                Min = Cow[i];        //下边为间接排序        for(int i = 1; i <= n; i++)            CowNo[i] = i;        sort(CowNo+1,CowNo+1+n,cmp);        res = 0;        for(int i = 1; i <= n; i++)        {            if(!Vis[i])            {                int Start = i;                int Mina = INF,Now = i,len = 0,Sum = 0;                do                {                    Vis[Now] = 1;                    len++;                    Sum += Cow[Now];                    if(Mina > Cow[Now])                        Mina = Cow[Now];                    Now = CowNo[Now];                }while(Now!=Start);                int Sum1 = Sum + (len-2)*Mina;                int Sum2 = Sum + Mina + (len+1)*Min;                res += min(Sum1,Sum2);            }        }        printf("%d\n",res);        //    for(int i = 1; i <= n; i++)        //        printf("%d %d\n",Cow[i],CowNo[i]);    }    return 0;}
0 0
原创粉丝点击