青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 30  文章 - 67  trackbacks - 0
<2011年3月>
272812345
6789101112
13141516171819
20212223242526
272829303112
3456789

常用鏈接

留言簿(8)

隨筆分類

隨筆檔案

文章檔案

收藏夾

Oops

搜索

  •  

積分與排名

  • 積分 - 86328
  • 排名 - 277

最新評論

閱讀排行榜

評論排行榜

 

今天主要是想回憶下DFS,所以就那全排列開刀了,自己寫了一個發現網上的解法真不錯就想總結下:

一、利用DFS實現(自己寫的)
廢話就不說了 上代碼:

#include <iostream>
#include 
<cstdio>
using namespace std;

const int size = 20;

bool visited[20];
int  arr[20];

int n;

void dfs(int cnt)
{
    
if( cnt == n)
    
{
        
for(int i = 0; i < n; ++i)
        
{
            cout 
<< arr[i] << " " ;
        }

        cout 
<< endl;
    }

    
else
    
{
        
for(int i = 1; i <= n; ++i )
        
{
            
if(!visited[i])
            
{
                arr[cnt] 
= i;
                visited[i] 
= 1;
                dfs(cnt
+1);
                visited[i] 
= 0;
            }

        }

    }

}



int main()
{

    
while(cin>>n)
    
{
        memset(visited, 
0sizeof(visited));
        dfs(
0);
    }


    
return 0;
}



這種方法,我沒有想好怎么實現含有相同元素的全全排列

二、利用遞歸實現,其實還是DFS,只是實現的方法不一樣,但是它能夠實現含有相同元素的全排列
下面給一段網上找的解釋,其實王曉東的那本《算法與設計》有這個:
令E={e1,e2...en}表示n個元素的集合,我們的目標是生成該集合的所有排列方式。令Ei為E中移去元素i以后所獲得的集合,perm(X)表示集合X中元素的排列方式,ei.perm(X)表示在perm(X)中的每個排列方式的前面均加上ei以后所得到的排列方式。例如,如果E={a,b,c},那么E1 = {b,c},perm(E1) = (bc,cb),e1.perm(E1) = (abc,acb)。

         對于遞歸的基本部分,采用n=1。當只有一個元素時,只可能產生一種排列方式,所以perm(E) = (e),其中e是E中的唯一元素。當n>1時,perm(E) = e1.perm(E1) + e2.perm(E2)+ e3.perm(E3)+.......+en.perm(En)。這種遞歸定義形式是采用n個perm(X)來定義perm(E),其中每個X包含n-1個元素。至此,一個完整的遞歸定義所需要的基本部分和遞歸部分都已完成。

下面給出我自己寫的代碼:

#include <iostream>
#include 
<cstdio>
using namespace std;

template
<class T>

void sswap(T &a, T &b)
{
    
if( a != b )
    {
        
int tmp = a;
        a 
= b;
        b 
= tmp;
    }
}

template
<class T>
void Perm(T list[], int k, int m)
{
    
if(k == m)
    {
        
for(int i = 0; i <= m; ++i)
        {
            cout 
<< list[i] << "";
        }
        cout 
<< endl;
    }
    
else
    {
        
for(int i = k; i <= m; ++i)
        {
           
// if( (list[k] != list[i]) || (k == i) ) //為了實現相同元素的全排
           
// {
                sswap(list[k], list[i]);
                Perm(list, k
+1, m);
                sswap(list[k], list[i]);
            
//}
        }
    }
}

int main()
{
    
int n;
    
int arr[10];

    
while(cin>>n)
    {
        
for(int i = 0; i < n; ++ i)
        {
            cin
>>arr[i];
        }

        Perm(arr, 
0, n - 1);
    }

    
return 0;
}



三、壓軸:STL next_permutation
 下面是網上的一段分析

C++/STL中定義的next_permutation和prev_permutation函數則是非常靈活且高效的一種方法,它被廣泛的應用于為指定序列生成不同的排列。本文將詳細的介紹prev_permutation函數的內部算法。

  按照STL文檔的描述,next_permutation函數將按字母表順序生成給定序列的下一個較大的排列,直到整個序列為降序為止。prev_permutation函數與之相反,是生成給定序列的上一個較小的排列。二者原理相同,僅遍例順序相反,這里僅以next_permutation為例介紹算法。

  先對序列大小的比較做出定義:兩個長度相同的序列,從兩者的第一個元素開始向后尋找,直到出現一個不同元素(也可能就是第它們的第一個元素),該元素較大的序列為大,反之序列為小;若一直到最后一個元素都相同,那么兩個序列相等。

  設當前序列為pn,下一個較大的序列為pn+1,這里蘊藏的含義是再也找不到另外的序列pm,使得pn < pm < pn+1。

  問題

  給定任意非空序列,生成下一個較大或較小的排列。

  過程

  根據上述概念易知,對于一個任意序列,最小的排列是增序,最大的為減序。那么給定一個pn要如何才能生成pn+1呢?先來看下面的例子:

  設3 6 4 2為pn,下一個序列pn+1應該是4 2 3 6。觀察第一個序列可以發現pn中的6 4 2已經為減序,在這個子集中再也無法排出更大的序列了,因此必須移動3的位置且要找一個數來取代3的位置。在6 4 2中6和4都比3大,但6比3大的太多了,只能選4。將4和3的位置對調后形成排列4 6 3 2。注意,由于4和3大小的相鄰關系,對調后產生的子集6 3 2仍保持逆序,即該子集最大的一種排列。而4是第一次移動到頭一位的,需要后面的子集為最小的排列,因此直接將6 3 2倒轉為2 3 6便得到了正確的一個序列pn+1。

  下面歸納分析該過程。假設一個有m個元素的序列pn,其下一組較大排列為pn+1:

  若pn的最后的2個元素構成一個最小的增序子集,那么直接反轉這2個元素使該子集成為減序即可得到pn+1。理由是pn和pn+1的前面m-2個元素都相等(沒有對前面的元素進行操作),僅能靠最后2個元素來分出大小。而這2個元素只能出現2種排列,其中較大的一種是減序。

  若pn的最后最多有s個元素構成一個減序子集,令i = m - s,則有pn(i) < pn(i+1),因此若將pn(i)和pn(i+1)調換必能得到一個較大的排列(不一定是下一個),因此必須保持pn(i)之前的元素不動,并在子集{pn(i+1), pn(i+2), ..., pn(m)}中找到一個僅比pn(i)大的元素pn(j),將二者調換位置。此時只要得到新子集{pn(i+1), pn(i+2), ..., pn(i), ...,pn(m)}的最小排列即可。注意到新子集仍保持減序,那么直接將其反轉即可得到最小的增序子集。

  按以上步驟便可從pn得到pn+1了。

  復雜度

  最好的情況為pn的最后的2個元素構成一個最小的增序子集,交換次數為1,復雜度為O(1),最差的情況為1個元素最小,而后面的所有元素構成減序子集,這樣需要先將第1個元素換到最后,然后反轉后面的所有元素。交換次數為1+(n-1)/2,復雜度為O(n)。這樣平均復雜度即為O(n/2)。

//STL的生成方法
bool my_next_permutation(int * const begin, int * const end)
{
    int *p1 , *p2;
    for(p1 = end - 1; p1!= begin; p1--)//找到序列中從后往前第一個元素1小于元素2的一對
    {
        if(*(p1-1)< *(p1))
            break;
    }
    if(p1==begin)//這種情況下序列已經完全逆序
        return false;
    p1--;//使p1指向小的那個數
    for(p2 = p1 + 1; p2 != end; p2++)//尋找p1后面比p1小但是最大的那個數
    //,這里利用了后面序列降序的性質
    {
        if(*p2 < *p1)
            break;
    }
    p2--;//p2指向后面比p1大但是最小的那個
    iter_swap(p1,p2);//交換p1,p2指向的元素
    reverse(p1+1,end);//注意是到end 反向而非p2
    return true;
}
 

請這樣調用

view plaincopy to clipboardprint?
do 
{  
    for(int i = 0; i < MAX; i++)  
    {  
        cout << d[i] << " ";  
    }  
    cout << endl;  
}while(my_next_permutation(d,d+MAX)); 
    do
    {
        for(int i = 0; i < MAX; i++)
        {
            cout << d[i] << " ";
        }
        cout << endl;
    }while(my_next_permutation(d,d+MAX));


部分內容引用:http://blog.csdn.net/heartnheart/archive/2010/10/20/5953150.aspx
posted on 2011-03-08 11:29 Cunch 閱讀(632) 評論(0)  編輯 收藏 引用 所屬分類: Algorithm
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧美精品伊人久久| 欧美大片免费观看| 亚洲欧美激情一区二区| 欧美日韩亚洲精品内裤| 一区二区三区精品| 99精品99| 国产欧美一区二区色老头| 久久精品视频导航| 久久亚洲欧洲| 一区二区激情视频| 午夜亚洲视频| 亚洲激情偷拍| 亚洲视频一区二区在线观看| 国产一区二区精品久久| 欧美成人精品激情在线观看| 欧美日韩中文精品| 久久国产精彩视频| 欧美不卡视频一区发布| 亚洲欧美国产三级| 久久在线免费视频| 亚洲视频欧美在线| 久久激情网站| 一区二区黄色| 久久精品视频在线观看| 在线视频亚洲欧美| 久久精品人人做人人爽| 一区二区成人精品 | 欧美1区2区视频| 欧美日韩国产一区二区三区地区 | 一区二区三区视频免费在线观看| 亚洲综合第一| 亚洲精品一区二区三区樱花| 午夜视频一区| 亚洲午夜久久久久久久久电影院| 久久精品国产精品亚洲精品| 亚洲午夜精品网| 久热精品视频| 久久精品成人一区二区三区蜜臀| 欧美精品导航| 欧美ed2k| 黄色成人在线网址| 亚洲小视频在线| 日韩一级片网址| 老司机亚洲精品| 久久五月天婷婷| 国产女精品视频网站免费| 日韩一级大片在线| 亚洲精品社区| 久久精品亚洲精品国产欧美kt∨| 午夜亚洲福利在线老司机| 欧美久久视频| 亚洲国产精选| 亚洲国产精品久久久久久女王| 欧美在线你懂的| 久久福利影视| 国产视频不卡| 欧美一级二级三级蜜桃| 欧美一级电影久久| 国产精品永久| 午夜在线视频观看日韩17c| 欧美一区国产二区| 国产麻豆精品视频| 老色批av在线精品| 久久福利一区| 久久久国产精彩视频美女艺术照福利| 国产精品久久久久久久久久久久久久| 亚洲人成在线观看一区二区| 亚洲激情不卡| 欧美刺激性大交免费视频| 欧美护士18xxxxhd| 亚洲精品视频免费| 欧美区高清在线| 亚洲精品久久久蜜桃| 亚洲午夜黄色| 国产精品户外野外| 亚洲欧美区自拍先锋| 久久久蜜桃一区二区人| 黄色在线成人| 欧美成人资源| 亚洲视频精选在线| 久久久久九九视频| 亚洲国产另类精品专区| 欧美日本一道本在线视频| 99在线热播精品免费| 久久激情婷婷| 亚洲电影欧美电影有声小说| 欧美福利视频在线| 夜夜嗨一区二区| 久久久久国产精品一区二区| 亚洲国产高清一区| 欧美乱人伦中文字幕在线| 亚洲综合二区| 你懂的国产精品| 亚洲视频在线观看三级| 国产自产在线视频一区| 欧美国产精品劲爆| 亚洲综合精品四区| 欧美国产三级| 欧美一级在线亚洲天堂| 亚洲片国产一区一级在线观看| 欧美日韩免费一区二区三区视频 | 亚洲国产精品成人一区二区| 亚洲一区二区三区高清| 精品91在线| 国产精品www网站| 久久一区二区三区超碰国产精品| 夜夜爽av福利精品导航| 另类激情亚洲| 亚洲欧美激情精品一区二区| 亚洲高清电影| 国产日产欧美a一级在线| 欧美精品电影在线| 久久久久久久综合日本| 亚洲午夜av| 欧美韩日亚洲| 久久影视精品| 午夜日本精品| 亚洲一区二区三区777| 亚洲人成在线观看一区二区| 国产午夜精品一区二区三区欧美 | 欧美精品激情| 久久尤物视频| 欧美亚洲日本国产| 国产精品99久久久久久有的能看 | 欧美成人综合一区| 久久噜噜噜精品国产亚洲综合 | 1769国内精品视频在线播放| 国产日产高清欧美一区二区三区| 欧美1级日本1级| 欧美精品一区在线发布| 新狼窝色av性久久久久久| 99精品99久久久久久宅男| 91久久精品一区| 欧美电影免费观看网站| 久久在线观看视频| 久久精品人人做人人综合| 午夜精品视频网站| 亚洲免费综合| 性欧美videos另类喷潮| 欧美一区二区三区另类| 亚洲综合精品自拍| 亚洲一区二区三区高清不卡| 亚洲制服少妇| 亚洲你懂的在线视频| 亚洲综合日韩在线| 亚洲欧美中文在线视频| 午夜久久美女| 久久国产乱子精品免费女| 久久久精品免费视频| 久久影院午夜论| 欧美黄污视频| 亚洲精品乱码久久久久久蜜桃麻豆 | 亚洲国产精品va在线看黑人| 亚洲国产精品一区在线观看不卡| 亚洲大胆人体视频| 亚洲三级免费观看| 在线亚洲精品| 欧美怡红院视频| 另类综合日韩欧美亚洲| 欧美黄色免费| 国产精品免费视频观看| 国内精品久久久久久久影视麻豆| 黄色成人av在线| 亚洲人成艺术| 亚洲欧美日韩天堂一区二区| 久久精品一区二区| 欧美激情精品久久久久久蜜臀| 亚洲每日在线| 欧美淫片网站| 欧美另类videos死尸| 国产日韩一区二区三区| 影音先锋日韩资源| 亚洲天堂免费观看| 久久久久久9999| 亚洲乱码国产乱码精品精天堂| 亚洲影院免费观看| 欧美成ee人免费视频| 国产精品爽爽爽| 亚洲欧洲日产国产网站| 午夜精品视频| 亚洲国产一区二区a毛片| 亚洲你懂的在线视频| 美女视频黄a大片欧美| 国产精品jvid在线观看蜜臀| 在线观看欧美一区| 亚洲综合第一| 亚洲激情专区| 久久久99国产精品免费| 欧美极品一区| 国产在线乱码一区二区三区| 一区二区日韩欧美| 美女网站在线免费欧美精品| 亚洲中无吗在线| 欧美理论在线| 亚洲国产99精品国自产| 久久久久在线观看| 一区二区三区日韩| 欧美激情一区二区三级高清视频| 狠狠色伊人亚洲综合网站色| 美女精品在线|