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

隨筆 - 30  文章 - 67  trackbacks - 0
<2013年6月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

常用鏈接

留言簿(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精品国产福利在线观看免费| 久久久精品999| 在线观看精品视频| 伊人久久噜噜噜躁狠狠躁| 国产亚洲欧洲997久久综合| 亚洲在线免费视频| 欧美一区二区三区的| 精品999网站| 亚洲精品国产精品国产自| 欧美成人精品在线播放| 亚洲永久免费av| 欧美综合国产| 亚洲美女一区| 亚洲欧美日韩一区在线| 影院欧美亚洲| 正在播放欧美一区| 亚洲第一狼人社区| 一区二区三区免费观看| 极品av少妇一区二区| 亚洲国产一区视频| 国产精品尤物福利片在线观看| 久久亚洲免费| 欧美性一区二区| 牛牛国产精品| 国产美女精品免费电影| 亚洲国内精品| 黄色亚洲精品| 亚洲午夜av在线| 亚洲欧洲精品天堂一级| 欧美一级大片在线免费观看| 日韩一级网站| 久久亚洲视频| 久久久九九九九| 国产精品成人免费| 亚洲第一搞黄网站| 国产一区二区黄| 一区二区三区视频在线| 亚洲日韩欧美视频一区| 久久精品久久99精品久久| 亚洲欧美视频在线观看视频| 欧美91大片| 欧美成人精品在线观看| 国产日韩欧美视频| 亚洲视频网在线直播| 一区二区三区**美女毛片| 久久综合久色欧美综合狠狠| 欧美一区激情| 国产精品网站一区| 亚洲一区在线观看视频 | 欧美精品观看| 欧美ed2k| 在线观看视频一区二区欧美日韩| 午夜影院日韩| 久久国产精品99国产精| 国产精品丝袜xxxxxxx| 亚洲视频香蕉人妖| 亚洲网站视频| 欧美手机在线| 中日韩在线视频| 亚洲欧美精品在线观看| 欧美三区视频| 亚洲一区二区三区涩| 亚洲欧美一区二区三区在线| 国产精品毛片在线看| 中文日韩电影网站| 欧美亚洲自偷自偷| 国产一区日韩二区欧美三区| 亚洲欧美日韩国产综合| 欧美一区二区在线视频| 久久精品91久久香蕉加勒比| 国产主播精品在线| 久久婷婷成人综合色| 欧美激情网友自拍| 一区二区三区久久久| 欧美无砖砖区免费| 欧美一区二区黄色| 欧美成人日本| 亚洲图片欧洲图片日韩av| 欧美午夜在线一二页| 午夜精品视频一区| 蜜桃视频一区| 亚洲视频香蕉人妖| 国产亚洲精品aa| 美女日韩欧美| 这里只有精品视频| 美女在线一区二区| 在线一区观看| 国产在线拍揄自揄视频不卡99| 久久久精品国产免大香伊| 亚洲激情一区二区三区| 欧美一级理论片| 亚洲高清二区| 国产精品www| 久久久久久高潮国产精品视| 亚洲精品影院| 久久久久国产精品www| 99re国产精品| 黄色一区二区三区| 欧美区国产区| 久久精品日产第一区二区| 亚洲人成小说网站色在线| 久久国产精品久久精品国产| 一本高清dvd不卡在线观看| 国产视频久久久久| 欧美国产免费| 久久精品国产一区二区电影| 亚洲免费观看在线观看| 男女视频一区二区| 欧美亚洲三区| 亚洲免费播放| 在线观看精品一区| 国产午夜一区二区三区| 欧美日韩一二三四五区| 麻豆视频一区二区| 欧美在线亚洲在线| 亚洲一区二区不卡免费| 亚洲日本中文字幕免费在线不卡| 久久噜噜噜精品国产亚洲综合| 亚洲一区在线免费观看| 日韩亚洲在线| 1024亚洲| 影音先锋欧美精品| 国内久久精品| 国产欧美 在线欧美| 欧美日韩一区二区免费在线观看| 蜜臀va亚洲va欧美va天堂| 久久久久成人网| 欧美在线不卡| 欧美一区二区性| 欧美一级欧美一级在线播放| 亚洲欧美日韩国产一区二区| 亚洲一区二区在线| 一区二区欧美精品| aa级大片欧美| 一本色道久久综合亚洲精品不卡 | 日韩一级成人av| 亚洲第一毛片| 亚洲第一成人在线| 亚洲国产高清aⅴ视频| 久久久欧美精品sm网站| 久久www成人_看片免费不卡| 亚洲一区二区毛片| 亚洲一区二区四区| 亚洲欧美日韩成人| 午夜精品福利一区二区三区av| 亚洲愉拍自拍另类高清精品| 亚洲欧美日韩成人高清在线一区| 亚洲欧美日韩网| 久久精品国产久精国产爱| 久久久久久久精| 欧美成人激情在线| 欧美日韩国产色站一区二区三区| 欧美日韩中文在线观看| 国产精品亚洲人在线观看| 国产精品主播| 在线视频观看日韩| 日韩五码在线| 午夜视频一区二区| 蜜臀久久99精品久久久久久9 | 亚洲女优在线| 久久人人97超碰国产公开结果| 蘑菇福利视频一区播放| 亚洲人成精品久久久久| 亚洲无限乱码一二三四麻| 欧美一级久久久| 欧美成人一区二区在线| 国产精品久久久久aaaa| 狠狠色狠狠色综合日日五| 亚洲免费播放| 久久国产精品99国产精| 亚洲国产精品久久| 亚洲一区中文字幕在线观看| 久久精品成人一区二区三区| 欧美成人免费观看| 国产精品推荐精品| 亚洲国产精品久久久久久女王| 亚洲一卡久久| 女人色偷偷aa久久天堂| 一区二区三区成人| 免费成人高清在线视频| 国产精品久久久久久久午夜 | 国产精品久久久久影院亚瑟| 在线成人激情黄色| 亚洲欧美日韩精品在线| 欧美大片在线观看| 亚洲欧美一区二区原创| 欧美成人免费在线视频| 国产一区二区0| 亚洲欧美激情一区| 91久久国产综合久久| 久久久之久亚州精品露出| 国产精品久久久一区麻豆最新章节 | 国产精品久久一区二区三区| 亚洲国产第一页| 久久精品国产亚洲5555| 亚洲视频在线观看视频| 女主播福利一区| 一区二区在线视频|