這題的核心演算法就是排列問題:
就目前常用的排列演算法有兩種:
一種是按字典列出排序,c++ stl所使用的方法,能夠支援重複元素的全排列。
另外一種是使用遞迴生成排序。
先說容易理解的一種方法,使用遞迴生成排序:
例如1,2,3,4,這個序列。
最開始,也就是遞迴最外層我們可以將其分成:
1 2,3,4,
2 1,3,4
3 1,2,4
4 1,2,3
這四個子分組:
然後遞迴到某乙個子分組當中比如2,3,4
於是就可以得到:
2 3,4
3 2,4
4 2,3
這三個子分組。
再次遞迴進入某乙個分組:
3 4
4 3
當只有第乙個數的時候,便不可分了,列印該排列。
於是遞迴的演算法可以寫成:
perm(int *list,int l,int r)按照字典列出排序的方法:break;
}else
}}
它的思想就是不斷的找到乙個排列中的下乙個排列,而且這兩個排列之間不會再有任何排列,整個排列都是從小到大排序的,
從右往左看,第乙個小於它的右邊的數是4,,13(4)987652。
然後從4右邊的數字開始,我們找到最後乙個大於它的數字5,1349876(5)2.。
然後調換4,5,得到數字串:13(5)9876(4)2.
翻轉5 後面的序列我們得到:13(5)2(4)6789
我們獲得的這個序列就是134987652的下乙個排列的數字。
為什麼呢?
我們仔細研究就會發現:
在第一步從右往左尋找第乙個比他右邊小的數字的時候,就是確定最後乙個遞減子串行的位置,直接將其翻轉就是該子串行的字典最小值,我們在翻轉之前需要變化遞減子串行的前乙個數字也就是4,[13(4)987652]。
確定該子串行的前乙個數,我們將遞減子串行當中的大於該數的最小數與它交換,在例子中也就是4和5交換,13(5)9876(4)2,於是我們可以知道,調換以後,遞減子串行9876(4)2依然保持遞減的特性,而遞減子串行之前的數字增大,遞減子串行之前的序列13(5)在字典序上恰好增大到下乙個字典子串行,這時,我們需要遞減子串行的最小字典子串行。
我們翻轉遞減子串行,得到遞減子串行的最小字典序987652,於是就得到了整個序列的遞增的下乙個字典序列。
字典實現排列演算法的**如下:
bool next_perm(int *list,int l,int r)說了這麼多,回到排列2這道題目上,我的ac**如下:int j=k;//取 k-1
while(j<=r&&list[j]>list[k-1])j++;
//取j-1
swap(list[k-1],list[j-1]);//交換list[k-1],list[j-1]
inverse(list,k,r);
for(int i=l;i<=r;i++)
printf("\n");
return true;
}
#include#include#include
#include
#include
using
namespace
std;
sets;
int cnt=0
;void
init()
void swap(int *a,int *b)
//遞迴演算法
void perm(int *list, int l,int
r)s.insert(v);
}else}}
intmain()
if(!first)printf("\n"
); first = false
; init();
perm(list,
0,3);
set::iterator iter;
int header = -1
;for(iter=s.begin();iter!=s.end();iter++)
if(header==value/1000
)if(header!=value/1000&&header!=-1)}
}printf("\n
");}return0;
}
杭電 1716 排列2
problem description ray又對數字的列產生了興趣 現有四張卡片,用這四張卡片能排列出很多不同的4位數,要求按從小到大的順序輸出這些4位數。input 每組資料佔一行,代表四張卡片上的數字 0 數字 9 如果四張卡片都是0,則輸入結束。output 對每組卡片按從小到大的順序輸出所...
杭電ACM題目分類
基礎題 1000 1001 1004 1005 1008 1012 1013 1014 1017 1019 1021 1028 1029 1032 1037 1040 1048 1056 1058 1061 1070 1076 1089 1090 1091 1092 1093 1094 1095 1...
杭電ACM 三 洗牌問題
每行乙個整數n 輸出與之對應的m 20 1 20 2 檔名稱 test.cpp 作 者 冷基棟 完成日期 2015年2月13日 版 本 號 v1.0 include using namespace std int main else if c 1 break m cout執行結果 知識點總結 關於這...