poj 3270 置換

 1 poj 3270  置換的應用 黑書原題P248
 2 /**
 3      題意: 給定序列, 將其按升序排列, 每次交換的代價是兩個數之和, 問代價最小是多少
 4      思路:一、對於同一個循環節以內的,確定是最小的與別的交換代價最小
 5                二、 對於整個序列中最小的與其交換 ,也可能最小
 6      比較這兩個大小,便可得出結論
 7      對於狀況1:代價爲 sum+(len-2)*t         //len 爲每一個循環節的長度, t 爲每一個循環節中最小的那個數  sum 爲循環節中所                                                          有數的和
 8      對於狀況2: 代價: sum+t+(len+1)*min  //  m爲整個序列中最小的數
 9 **/
10 
11 #include <iostream>
12 #include <cstring>
13 #include <cstdio>
14 using namespace std;
15 int n,Max,Min;
16 const int maxn = 10005;
17 bool vis[maxn];
18 int num[maxn],pos[maxn*10];
19 
20 void countSort(){
21     Max = -maxn*10;
22     Min = maxn*10;
23     memset(pos,0,sizeof(pos));
24     for(int i=1;i<=n;i++){
25         pos[num[i]] =1;
26         if(num[i]<Min) Min = num[i];
27         if(num[i]>Max) Max = num[i];
28     }
29     for(int i=1;i<=Max;i++){
30         pos[i] += pos[i-1];
31     }
32 }
33 
34 int solve(){
35     int ans =0;
36     memset(vis,0,sizeof(vis));
37     for(int i=1;i<=n;i++){
38         int len =0,temp = i,sum =0,tMin = maxn*10;
39         while(!vis[temp]){
40             vis[temp] = true;
41             len ++;
42             sum += num[temp];
43             if(num[temp]<tMin) tMin = num[temp];
44             temp = pos[num[temp]];
45         }
46         if(len>0){
47             int res1 = sum + (len-2)*tMin,res2 =sum + tMin+ (len+1)*Min;
48             ans += res1<res2?res1:res2;
49         }
50     }
51     return ans;
52 }
53 
54 int main()
55 {
56     int i;
57     scanf("%d",&n);
58     for(i=1;i<=n;i++)
59         scanf("%d",&num[i]);
60     countSort();
61     printf("%d\n",solve());
62 
63     return 0;
64 }
相關文章
相關標籤/搜索