cow sorting

 

/*題意:給出一列數的初始狀態,叫你求要達到從小到大排序,至少要劃分多少工作, 工作定義:每次交換兩個
則這次操作的工作爲兩個被交換的數的和

思路:置換羣寫法:定義三個數組cow【】存儲牛的輸入,acow【】存儲目標狀態,hash【cow【】】存儲每隻牛的
初始位置  vis【】記錄有沒有被動過,接着就是找出n個裏面的輪換,計算每個輪換的長度和記錄他們之中最小值
爲了得到最優解,可以多一步操作,將n個數裏的最小值和某個輪換裏的最小值交換,讓那個最小值參與輪換,
設輪換裏的最小值爲t,n個數裏的最小值爲min,k爲輪換的長度,最後再判斷t*(k-2)和t+min*(k+1)的大小
取最小那個,所以最後的解爲:n個數的和加上:
  n
k=∑ min(t*(k-2),t+min*(k+1)),所以結果爲sum+k
  i=1
  */

 

 

 

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int cow[10010],acow[10010];//目標狀態存在acow中
int hash[100010];//存儲每隻牛的下標
bool vis[10010];//找過的牛置爲1
int main()
{
 int n,i,sum,qmin,bmin;
 while(scanf("%d",&n)!=EOF)
 {
  qmin=1<<25;
  memset(vis,false,sizeof(vis));
  sum=0;
  for(i=0;i<n;i++)
  {
   scanf("%d",&cow[i]);
   acow[i]=cow[i];
   hash[cow[i]]=i;
   sum=sum+cow[i];
   if(cow[i]<qmin) qmin=cow[i];
  }
  sort(acow,acow+n);
  int lehn=n,ans=0,leh;
  while(lehn)
  {
   i=leh=0;
   bmin=1<<25;
   while(vis[i]) i++;//找到輪換的起點
            int begin=i;//記錄起點,便於判斷是不是已經循環完了
   while(1)
   {
                 leh++;
     vis[i]=1;
     if(cow[i]<bmin) bmin=cow[i];
     i=hash[acow[i]];
     if(i==begin) break;
   }
             lehn-=leh;//長度減去輪換的長度,等於剩下的所有長度
     // if(leh==1) continue;//只有一個元素的循環不需要變動

   int V1=(leh-2)*bmin;
   int V2=(leh+1)*qmin+bmin;
   ans+=V1<V2?V1:V2;

  }
  printf("%d\n",ans+sum);
 }
 return 0;
}

 

發佈了41 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章