第二届河南省大学生程序设计竞赛 试题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