1. 程式人生 > >第四章實踐報告

第四章實踐報告

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.結對心得

這道題是我的同伴打的,他非常細心地向我講解了此題的方法和策略。最優合併問題幫助我更直觀地瞭解了貪心演算法,還有庫函式的使用。