【BZOJ 1697】1697: [Usaco2007 Feb]Cow Sorting牛排序
1697: [Usaco2007 Feb]Cow Sorting牛排序
Description
农夫JOHN准备把他的 N(1 <= N <= 10,000)头牛排队以便于行动。因为脾气大的牛有可能会捣乱,JOHN想把牛按脾气的大小排序。每一头牛的脾气都是一个在1到100,000之间的整数并且没有两头牛的脾气值相同。在排序过程中,JOHN 可以交换任意两头牛的位置。因为脾气大的牛不好移动,JOHN需要X+Y秒来交换脾气值为X和Y的两头牛。 请帮JOHN计算把所有牛排好序的最短时间。
Input
第1行: 一个数, N。
第2~N+1行: 每行一个数,第i+1行是第i头牛的脾气值。
Output
第1行: 一个数,把所有牛排好序的最短时间。
Sample Input
3
2
3
1
输入解释:
队列里有三头牛,脾气分别为 2,3, 1。
Sample Output
7
输出解释:
2 3 1 : 初始序列
2 1 3 : 交换脾气为3和1的牛(时间=1+3=4).
1 2 3 : 交换脾气为1和2的牛(时间=2+1=3).
【分析】
又傻了,想了很久,只想到第一种情况,以为这就是最优的。
其实就是一种置换,要把它换回原位。
先分解成互不相交的循环。
对于同一个循环里面的元素,最好就是每次都用最小的一个和别人交换,代价是sum + (len – 2) * min
其实的话,还有一种,就是先把一个全局最小的移过来,换完了之后再移回去,代价是sum + min + (len + 1) * smallest
取两种方法中最小的一个。
至于为什么只有这两种,我也不太清楚,但想想好像跨组的情况除了第二种也没什么可以更优的了。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 10010 8 #define INF 0xfffffff 9 10 struct node 11 { 12 int a,b,id; 13 }t[Maxn]; 14 15 bool vis[Maxn]; 16 17 int mymin(int x,int y) {return x<y?x:y;} 18 int mymax(int x,int y) {return x>y?x:y;} 19 20 bool cmp(node x,node y) {return x.a<y.a;} 21 bool cmp2(node x,node y) {return x.id<y.id;} 22 23 int main() 24 { 25 int n,ans=0,mnn=INF,mx=0; 26 scanf("%d",&n); 27 for(int i=1;i<=n;i++) 28 { 29 // scanf("%d",&a[i]); 30 scanf("%d",&t[i].a); 31 t[i].id=i; 32 mnn=mymin(mnn,t[i].a); 33 mx=mymax(mx,t[i].a); 34 } 35 sort(t+1,t+1+n,cmp); 36 for(int i=1;i<=n;i++) t[i].b=i; 37 sort(t+1,t+1+n,cmp2); 38 memset(vis,0,sizeof(vis)); 39 for(int i=1;i<=n;i++) if(vis[i]==0) 40 { 41 int mn=INF,x=i,h=0,cnt=0; 42 while(vis[x]==0) 43 { 44 cnt++; 45 vis[x]=1; 46 mn=mymin(mn,t[x].a); 47 h+=t[x].a; 48 x=t[x].b; 49 } 50 ans+=mymin((cnt-2)*mn+h,h+mn+(cnt+1)*mnn); 51 } 52 printf("%d\n",ans); 53 return 0; 54 }
2017-01-12 19:53:21