第二届河南省大学生程序设计竞赛 试题4 壮观的瓷器广场

【试题四】
壮观的瓷器广场
【问题描述】
最近,某瓷都为了体现“千年瓷都” 的风貌,将要建立一个壮观的瓷器广场迎接来自各国的宾客。,顾问Dr.Kong提出了一项建议:在巨大的广场南面展示N件高度不等的瓷器灯柱。夜间,这些瓷器灯柱逐一闪亮,由低至高,如此场景必将十分的绚丽夺目。
然而,在瓷器灯柱运来安放后,Dr.Kong才发现粗心的工人并没有按照从低到高的顺序安放瓷器灯柱。由于瓷器灯柱已经竖立起来,不可能全部推倒重新安放,人力又搬不动。因此,Dr.Kong只能借助巨型吊车每次将两个瓷器灯柱的位置小心翼翼地进行交换。 例如,有3个瓷器灯柱初始时高度顺序是:3 1 2。可以先用吊车交换后两个灯柱的位置,得到3 2 1,再交换第一和第三个灯柱,得到最终序列1 2 3。 毕竟,用吊车交换灯柱位置可不是一件容易的事情,灯柱越高其重量越大,交换的难度也就越高。Dr.Kong估算出,每一次交换的难度等于交换的两个灯柱的高度的和。而整个交换方案的难度等于每次交换难度的总和。 例如先前的交换方案。原先3 1 2,交换后两个(难度为1+2=3),得到3 2 1,再交换第一和第三个(难度为3+1 = 4),得到1 2 3。因此,该方案的难度为3+4 =7。 为了使交换工作尽快完成,难度最低的交换方案自然是首选了。Dr.Kong虽然知道一些选择,冒泡,归并,快速甚至堆排序等。然而,在该问题面前,这些方法看起来似乎毫无用武之地!你有何办法?
【标准输入】
第一行: M 表示以下有M组测试数据(0<M<=8)
接下来每组有两行数据
头一行: N (表示瓷器灯柱的数目1 ≤ N ≤ 100 ) 下一行: H1 H2 ….Hn (表示依次安放灯柱的高度, 1≤Hi≤ 1000,)
【标准输出】
输出有M行,第i行为仅包含一个整数, 为第i组测试数据可得到的交换方案的最低难度值。
【 样 例 】
标准输入
标准输出
2 3
3 1 2
4 30 40 10 23
7 103

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 using namespace std;
 5 int l[105],al[105];
 6 int hash[1005];
 7 bool vis[105];
 8 int main(){
 9     int M,N;
10     int rmin=1000;
11     int i,length,ans;
12     scanf("%d",&M);
13     while(M--){
14         scanf("%d",&N);
15         for(ans=i=0;i<N;i++){
16             scanf("%d",&l[i]);
17             al[i]=l[i];
18             hash[l[i]]=i;
19             if(rmin>l[i]) rmin=l[i];
20         }
21         sort(al,al+N);
22         for(i=0;i<N;i++)
23             printf("%d ",al[i]);
24         puts("");
25         memset(vis,0,sizeof(vis));
26         length=N;
27         while(length>0){
28             int i=0,len=0;
29             int min=1000;
30             while(vis[i]) i++;
31             int begin=i;
32             int sum1,sum2,sum=0;
33             while(1){
34                 len++;
35                 if(min>l[i]) min=l[i];
36                 vis[i]=1;
37                 sum+=l[i];
38                 i=hash[al[i]];
39                 if(i==begin) break;
40             }
41             length-=len;
42             if(len==1) continue;
43             sum1=sum+(len-2)*min;
44             sum2=sum+min+(len+1)*rmin;
45             ans+=(sum1>sum2 ? sum2 : sum1);
46         }
47         printf("%d\n",ans);
48     }
49     while(1);
50     return 0;
51 }

做这道题复习了以前学的置换群:这道题和POJ3270一样!参见POJ3270

原文地址:https://www.cnblogs.com/shihuajie/p/3043542.html