算法--電路布線問題


 在一塊電路板的上、下兩端分別有n個接線柱。根據電路設計,要求用導線將上端接線柱與下端接線柱相連

 

如上圖所示,每個節點有且只連有一條線。 
在制作電路板時,要求將這n條連線分布到若干絕緣層上。在同一層上的連線不相交。 
這個問題是要確定將哪些連線安排在第一層上,使得該層上有盡可能多的連線(不相交)。 
為了解決這個問題,我們可以 將問題簡化為這樣: 
設定上接線柱為1,2,3,....,n。 
下接線柱是【 1,2,3,....,n】的一個排列 設為f(i),i的值就是上接線柱的數字, 
如上圖就是這樣的模型: 
i    1    2     3    4   5   6    7    8     9    10 
f(i) 8,7,4,2,5,1,9,3,10,6 
它們一一對應。  
我們還必須得到這樣一個結論: 
對於上接線柱i1<i2<i3<...<ik來說。它們與下接線柱f(i)的連線之間互不相交的充要條件是: 
f(i1)<f(i2)<...<f(ik)。這個結論是很顯然成立的。 
因為對於i1<i2如果f(i1)>f(i2)則它們一定相交(畫出圖像來看看) 
因此,我可以將這個電路布線問題,轉化為這樣的問題: 
已知有一個{1,2,3,...,n}的排列,將其拆分為k個子排列,並且每個子排列都是嚴格遞增的,求子排列的最大元素個數。 
例如:排列 8,7,4,2,5,1,9,3,10,6可以拆分成五個子排列{4,5,9,10}{8}{7}{2,3,6}{1} 。 
它最大的元素個數是4。 
排列 1,2,3,4,5,6,7,8,9,10它是遞增的,所以無需拆分,最大元素個數是10。 
算法實現: 
對於排列8,7,4,2,5,1,9,3,10,6。 
先將記錄第一個值8,依次向后掃描至大於8的元素。如果發現8的元素,例如9,則我可以產生一個子排列{8,9}(實際上只需要更改元素數量和最大值即可),繼續掃描。 
產生子排列{8,9,10}。掃描完畢后姑且認為子排列最大元素是3個。 
第二次以7向后掃描,只要掃描到比它大的,就將產生一個子排列,繼續向后掃描,掃描結束后,得到排列是{7,9,10}。個數是3,與之前的比較。 
第三次以4開始掃描,。。。依次下去至掃描結束。  
使用遞歸算法代碼簡單,算法復雜度為O(N*N)

 

復制代碼
#include <iostream>
using namespace std;
#define N 10


int sub[N] = { 2, 7, 3, 4, 5, 6, 9, 8, 10, 1 };

int function(int MaxElem,int e=0,int counts=1)
{
    if (e==N-1)
    {
        //遞歸的出口
        if (sub[e] > MaxElem) counts++;
        return counts;
    }
    else
    {
        if (sub[e]>MaxElem)
        {
            MaxElem = sub[e];
            counts++;

        }
        return function(MaxElem,e+1,counts);
    }

}

int main()
{    
    int max = 0,t;
    for (int i = 0; i < N; i++)
    {
        if ((t = function(sub[i]))>max) max = t;
    }
    cout << max << endl;
    

    return 0;
}
復制代碼


免責聲明!

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



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