http://poj.org/problem?id=3270
给n头牛 让你把他们升序排序 每次交换两个牛 交换花费是两个牛值之和
求最小花费
黑书上有 P248 求循环
每个循环进行判断 一个循环的花费有两种情况可能为最优
1 用循环内最小的花费牛 和其他牛 进行交换
2 或是用全局最小花费牛 先和本环内最小花费牛交换 然后一样 最后再交换回来就可以了
代码及其注释:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<cmath>
#define LL long long
using namespace std;
const int N=10005;
struct node
{
int I;
int k;
}mem[N];
int MIN;
bool cmp(node x,node y)
{
return x.k<y.k;
}
int polya(int n)
{
bool had[N];
memset(had,false,sizeof(had));
int ans=0;
for(int i=1;i<=n;++i)
{
if(!had[i])//每个环 判断
{
had[i]=true;
int num=1;
int sum=mem[i].k;
int m=mem[i].k;
int l=mem[i].I;
while(l!=i)
{
had[l]=true;
num++;
sum+=mem[l].k;
m=min(m,mem[l].k);
l=mem[l].I;
}
ans=ans+min((sum-m+m*(num-1)),((sum-m+MIN)-MIN+MIN*(num-1)+2*(MIN+m)));//两种情况取最小
//cout<<ans<<endl;
}
}
return ans;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
MIN=N;
for(int i=1;i<=n;++i)
{
mem[i].I=i;;//位置
scanf("%d",&mem[i].k);//花费
MIN=min(MIN,mem[i].k);//求全局最小花费
}
sort(mem+1,mem+n+1,cmp);//排序
printf("%d\n",polya(n));
}
return 0;
}
浙公网安备 33010602011771号