交換最少次使數列有序
阿新 • • 發佈:2018-06-25
比較 amp targe tps 最小值 一個數 pac cas eof
問題 A: 【雜題】排序
時間限制: 1 Sec 內存限制: 128 MB題目描述
有一列數,要對其進行排序(升序)。排序只能通過交換來實現。每次交換,可以選擇這列數中的任意兩個,交換他們的位置,並且交換的代價為這兩個數的和。排序的總代價是排序過程中所有交換代價之和。現要求計算,對於任意給出的一列數,要將其排成升序所需的最小代價。輸入
輸入包含多組數據。每組數據有兩行組成。第一行一個數n,表示這列數共有n個數組成。第二行n個互不相同的整數(都是小於1000的正整數),表示這列數。輸入文件以n=0結尾。輸出
對於每組輸入數據,輸出組號和排序所需的最小代價。樣例輸入
3 3 2 1 4 8 1 2 4 5 1 8 9 7 6 6 8 4 5 3 2 7 0
樣例輸出
Case 1: 4
Case 2: 17
Case 3: 41
Case 4: 34
首先要明白最小交換次數的算法,大致就是n - n被分解成單循環的個數
具體參照這個博客https://blog.csdn.net/wangxugangzy05/article/details/42454111
然後這題就離散化一下,找出每個單循環,比較計算最小值就行了
#include<bits/stdc++.h> using namespace std; int n,team3[100000]; int team[100000]; int Sum,Min,Num; int check[100000]= {0View Code}; void f(int x) { if(check[x]==1)return; Sum+=team[x]; Min=min(Min,team[x]); Num++; check[x]=1; f(team3[x]); } int main() { int tot=0,ans=0,all_min=INT_MAX; int team2[100000]; while(scanf("%d",&n)==1) { if(n==0)return 0; all_min=INT_MAX; ans=0; for(int i=1; i<=n; i++)scanf("%d",&team[i]),team2[i]=team[i],all_min=min(all_min,team[i]); sort(team2+1,team2+1+n); int size=unique(team2+1,team2+1+n)-team2-1; for(int i=1; i<=n; i++) team3[i]=lower_bound(team2+1,team2+1+size,team[i])-team2; memset(check,0,sizeof(check)); for(int i=1; i<=n; i++) if(check[i]==0) { Sum=0; Min=INT_MAX; Num=0; f(i); ans+=min(Min*(Num-1),all_min*(Num-1)+2*(Min+all_min))+(Sum-Min); } printf("Case %d: %d\n\n",++tot,ans); } return 0; }
交換最少次使數列有序