最優合並問題


最優合並問題

Time Limit: 1000 ms Memory Limit: 65536 KiB
 

Problem Description

給定k 個排好序的序列s1 , s2,……, sk , 用2 路合並算法將這k 個序列合並成一個序列。假設所采用的2 路合並算法合並2 個長度分別為m和n的序列需要m + n -1次比較。試設計一個算法確定合並這個序列的最優合並順序,使所需的總比較次數最少。
為了進行比較,還需要確定合並這個序列的最差合並順序,使所需的總比較次數最多。
對於給定的k個待合並序列,計算最多比較次數和最少比較次數合並方案。
 

Input

輸入數據的第一行有1 個正整數k(k≤1000),表示有k個待合並序列。接下來的1 行中,有k個正整數,表示k個待合並序列的長度。

Output

輸出兩個整數,中間用空格隔開,表示計算出的最多比較次數和最少比較次數。

Sample Input

4
5 12 11 2

Sample Output

78 52

Hint

 

Source

 

使用 優先隊列  優化 ,使用模板

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 template<typename T>
 5 int result(T q){//使用模板  因為求最大 最小值 ,這兩個 代碼幾乎一樣
 6     int rst=0;
 7     while((int)q.size()>2){//兩個求和
 8         int sum=0;
 9         for(int i=0;i<2;i++){
10             sum+=q.top();
11             q.pop();
12         }
13         rst+=sum;
14         q.push(sum);
15     }
16     while(!q.empty()){
17         rst+=q.top();
18         q.pop();
19     }
20     return rst;
21 }
22 int main()
23 {
24     priority_queue<int,vector<int>,less<int> > q;//從大到小  Max
25     priority_queue<int,vector<int>,greater<int> > p;// 從小 到大 Min
26     int n,data;
27     cin>>n;
28     for(int i=0;i<n;i++){
29         cin>>data;
30         q.push(data);
31         p.push(data);
32     }
33     int  maxNum=result(q);//2 路合並算法合並2 個長度分別為m和n的序列需要m + n -1次比較 
34     int  minNum=result(p);
35     cout<<maxNum-(n-1)<<" "<<minNum-(n-1)<<endl;// 所以總共 比較n-1次  最后減去 n-1即可
36     return 0;
37 }

 

初始:未優化

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     priority_queue<int,vector<int>,less<int> > q;//從大到小  Max
 6     priority_queue<int,vector<int>,greater<int> > p;// 從小 到大 Min
 7     int n,data;
 8     cin>>n;
 9     for(int i=0;i<n;i++){
10         cin>>data;
11         q.push(data);
12         p.push(data);
13     }
14     int  maxNum=0;//初始化 最大 費用 0
15     int  minNum=0;//初始化 最小 費用 0
16     while((int)q.size()>2){
17         int sumMax=0,sumMin=0;
18         for(int i=0;i<2;i++){
19             sumMax+=q.top();
20             q.pop();
21             sumMin+=p.top();
22             p.pop();
23         }
24         maxNum+=sumMax;
25         minNum+=sumMin;
26         q.push(sumMax);
27         p.push(sumMin);
28     }
29     while(!q.empty()){
30         maxNum+=q.top();
31         minNum+=p.top();
32         q.pop();
33         p.pop();
34     }
35     cout<<maxNum-(n-1)<<" "<<minNum-(n-1)<<endl;
36     return 0;
37 }

 

使用數組

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 
 6 bool cmp(int a, int b){
 7     return a>b;
 8 }
 9 
10 int main(){
11     int k;
12     int a[1010], b[1010];
13     int Min = 0, Max = 0;//此算法 ,和優先隊列 差不多,每次將 算出的 最小值,最大值,在放進隊列中 ,進行比較
14     cin>>k;
15     for(int i=0; i<k; i++){
16         cin>>a[i];
17         b[i]= a[i];
18     }//當取最小值保證每次的2個加數為最小便可,最大值同理取當前最大的兩個值便可
19     sort(a, a+k);//最小值 排序 從小到大
20     sort(b, b+k, cmp);// 將 數據 從大到小 排序
21     for(int i=0; i<k-1; i++){
22         a[i+1] = a[i]+a[i+1];//當前 開始的 下一個 值  替換為   前兩個 數之和,
23         Min += a[i+1];//最小值 更新 為 兩個 最小值   最后 才算了 -(k-1)  因為 k 個數 ,要進行 k-1次比較 ,得減去 k-1 個 1  ; k-1次 (m+n-1)
24         sort(a+i+1, a+k);
25 
26         b[i+1] = b[i]+b[i+1];//此處為 最大值 ,每次加過 之和,在放進 要進行合並的序列中  在進行參與比較
27         Max += b[i+1];
28         sort(b+i+1, b+k ,cmp);
29     }
30     cout<<Max-k+1<<' '<<Min-k+1<<endl;
31     return 0;
32 }

 

 

 1 函數模板的聲明形式為:
 2 template<typename(或class) T>
 3 <返回類型><函數名>(參數表)
 4 {
 5 函數體
 6 }
 7 其中,template是定義模板函數的關鍵字;template后面的尖括號不能省略;typename(或class)是聲明數據類型參數標識符的關鍵字,用以說明它后面的標識符是數據類型標識符。這樣,在以后定義的這個函數中,凡希望根據實參數據類型來確定數據類型的變量,都可以用數據類型參數標識符來說明,從而使這個變量可以適應不同的數據類型。例如:
 8 template<typename(或class) T>
 9 T fuc(T x, T y)
10 {
11 T x;
12 //……
13 }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM