第四章實踐報告
阿新 • • 發佈:2018-11-28
7-1最優合併問題
1.問題描述:
給定k 個排好序的序列, 用 2 路合併演算法將這k 個序列合併成一個序列。 假設所採用的 2 路合併演算法合併 2 個長度分別為m和n的序列需要m+n-1 次比較。試設 計一個演算法確定合併這個序列的最優合併順序,使所需的總比較次數最少。 為了進行比較,還需要確定合併這個序列的最差合併順序,使所需的總比較次數最多。
輸入格式:第一行有 1 個正整數k,表示有 k個待合併序列。 第二行有 k個正整數,表示 k個待合併序列的長度。
輸出格式:輸出最多比較次數和最少比較次數。
輸入樣例:在這裡給出一組輸入。例如:
4
5 12 11 2
輸出樣例:在這裡給出相應的輸出。例如:
78 52
2.貪心策略
每次選最小的兩個序列合併得到較小比較次數;每次選最大的兩個序列合併得到較大的比較次數。
兩個長度分別為m和n的序列需要m+n-1次比較,此題樣例的計算路徑為:
較小:((2+5-1)+((2+5-1)+11-1))+(2+5+11+12-1)=6+17+29=52
較大同理。
3.詳細程式碼及註釋
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int k;
cin>>k;
int *a = new int[k+1 ];
int *b = new int[k+1];//設定兩個陣列,一個求最大次數,一個求最小次數
for(int i=0;i<k;i++)
{
cin>>a[i];
b[i] = a[i];
}
sort(a,a+k);//庫函式,(a,a+k)表示從左到右遍歷
int min=0;
for(int n=0;n<k-1;n++)//此處迴圈求最小比較次數
{
min =min + a[n] + a[n+1] -1;//最小次數=上次路徑最小次數+m+n-1
a[n] = a[n] + a[n+1];//類似哈弗曼樹,a[n]=排序後兩個最小次數之和
a[n+1] = 0;//把其中一個數設定為0
sort(a,a+k);//呼叫庫函式
}
sort(b,b+k);
int max = 0;
for(int i=1;i<=k-1;i++)
{
max = max +b[k-1]+b[k-2]-1;
b[k-1]=b[k-1]+b[k-2];
b[k-2]=0;
sort(b,b+k);
}
cout<<max<<" "<<min<<endl;
return 0;
}
3.演算法時間及空間複雜度
當n=1時,就成了m個數的歸併排序,時間複雜度為O(mlogn)。
4.結對心得
這道題是我的同伴打的,他非常細心地向我講解了此題的方法和策略。最優合併問題幫助我更直觀地瞭解了貪心演算法,還有庫函式的使用。