POJ 3270 Cow Sorting 置换应用

来源:互联网 发布:帝国时代2mac版中文 编辑:程序博客网 时间:2024/05/17 21:54
点击打开链接

Cow Sorting
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 5638 Accepted: 2144

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

3231

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).

Source

USACO 2007 February Gold


给你一个无序数组,通过一系列对换使之有序。对换的花费是对换两个数的和。问最小花费是多少。
将原有的序列排序后,形成目标串,这样就与原串形成了置换。例如给你原串是4,2,8, 6,7,目标串是2,4,6,7,8。这样就形成了两个环(4,2)和(8,6,7)。当然最优解是在同一个环内进行交换,如果在环与环之间交换的话,会增加费用。如果环的长度为m,则需要交换次数最少是m-1才能排好序。花费是sum - min + (len - 1) * min。化简后为:
sum + (len - 2) * min。其中,sum为这个循环所有数字的和,len为长度,min为这个环里面最小的数字。
还有一种特殊情况,如果最小元素不在这个环里,那么就要用环外的这个最小元素与环内的元素进行交换,花费是sum + min + (len + 1) * smallest
其中,sum为这个循环所有数字的和,len为长度,min为这个环里面最小的数字,smallest是整个数列最小的数字。
.因此,对一个循环的排序,其代价是sum - min + (len - 1) * min和sum + min + (len + 1) * smallest之中小的那个数字。
//564K547MS#include<stdio.h>#include<string.h>#include<algorithm>#define inf 0x3f3f3f#define M 10007#define minn(a,b) a<b?a:busing namespace std;bool vis[M];int first[M],last[M],minn,n,tot;//first为排序前的序列,last为排序后的序列,tot为环的个数,minn为整个序列的最小值struct sa{    int len;//环的长度    int minn;//环的最小值}cir[M];void dfs(int x)//寻找在同一个环中的元素{    for(int i=0;i<n;i++)//在排序前的元素中找        if(!vis[i]&&x==first[i])//如果找到且没有访问过        {            vis[i]=true;            cir[tot].len++;            cir[tot].minn=min(cir[tot].minn,first[i]);            dfs(last[i]);        }}int main(){    scanf("%d",&n);    minn=inf;tot=0;    memset(vis,false,sizeof(vis));    int ans=0;    for(int i=0;i<n;i++)    {        scanf("%d",&first[i]);        last[i]=first[i];        ans+=first[i];//ans为总的价值        minn=min(minn,first[i]);    }    sort(last,last+n);    for(int i=0;i<n;i++)    {        if(vis[i])continue;//如果访问过,就访问下一个        cir[tot].len=1;        cir[tot].minn=first[i];        vis[i]=true;        dfs(last[i]);        tot++;    }    for(int i=0;i<tot;i++)        ans+=minn(cir[i].minn*(cir[i].len-2),minn*(cir[i].len+1)+cir[i].minn);//去两种情况中的最小值    printf("%d\n",ans);}


0 0
原创粉丝点击