格雷碼、全排列、約瑟夫環、m個元素中求n個元素的所有集合
阿新 • • 發佈:2018-12-13
格雷碼:
格雷碼是指,通過0-1的串來求出對應位數的所有可能。例如2的格雷碼:00、01、10、11
//格雷碼 例如2:00 01 10 11 void print(vector<int> &veNum) { for (int i = 1; i < veNum.size(); ++i) cout << veNum[i] << " "; cout << endl; } void printallnum(int iNum) { if (iNum <= 0) return; vector<int> veNum(iNum + 1); int ipos = iNum; while (true) { ipos = iNum; while (ipos > 0 && veNum[ipos] == 1) veNum[ipos--] = 0; if (ipos == 0) break; else veNum[ipos] = 1; print(veNum); } } int main() { int iNum = 0; cin >> iNum; printallnum(iNum); return 0; }
求n個元素的所有可能的組合:
給定n個元素,求著n個元素的所有可能,也就是他的所有子集。這可以看成是格雷碼問題的一種變形問題:
//所有可能的集合 12-> 1 2 12 格雷碼的變形 void print(vector<int> &veNum, int ar[], int iLen) { for (int i = 1; i < veNum.size(); ++i) { if (veNum[i]) cout << ar[i - 1]; } cout << endl; } void allprint(int ar[], int iLen) { if (ar == NULL || iLen <= 0) return; vector<int> veNum(iLen + 1); while (true) { int iPos = iLen; while (iPos > 0 && veNum[iPos] == 1) veNum[iPos--] = 0; if (iPos == 0) return; else veNum[iPos] = 1; print(veNum, ar, iLen); } } int main() { int ar[] = { 1, 2, 3, 4 }; int iLen = sizeof(ar) / sizeof(ar[0]); allprint(ar, iLen); return 0; }
m個元素中求n個元素的所有集合:
求m個元素的集合中,任意n個元素對應的所有集合。
void allprint(int iAllLen, int n) { if (iAllLen < n) return; else if (iAllLen == n) { for (int i = 0; i < n; ++i) cout << i+1; cout << endl; } else { vector<int> veNum(iAllLen + 1); for (int i = 0; i <= iAllLen; ++i) veNum[i] = i; //列印初始值 for (int i = 1; i <= n; ++i) cout << veNum[i]; cout << endl; int iposition = n ; while (1) { if (veNum[n] == iAllLen) iposition--; else iposition = n; veNum[iposition]++; for (int i = iposition + 1; i <= n; ++i) veNum[i] = veNum[i - 1] + 1; for (int i = 1; i <= n; ++i) cout << veNum[i]; cout << endl; if (veNum[1] >= iAllLen - n + 1) break; } } } int main() { int iAllLen = 6; int n = 4; allprint(iAllLen, n); return 0; }
上邊的求解是假設初始的m的集合是從1開始並且順序增加的數字。如果是任意的陣列集合,可以根據求出的數字來確定對應的下標進行求解該問題。
//m個元素中n個元素的所有集合 改問題的變形 詳情參考該問題
void allprint(int ar[], int iAllLen, int n)
{
if (iAllLen < n)
return;
else if (iAllLen == n)
{
for (int i = 0; i < n; ++i)
cout << ar[i];
cout << endl;
}
else
{
vector<int> veNum(iAllLen + 1);
for (int i = 0; i <= iAllLen; ++i) veNum[i] = i;
//列印初始值
for (int i = 1; i <= n; ++i)
cout << ar[veNum[i] - 1];
cout << endl;
int iposition = n;
while (1)
{
if (veNum[n] == iAllLen)
iposition--;
else
iposition = n;
veNum[iposition]++;
for (int i = iposition + 1; i <= n; ++i)
veNum[i] = veNum[i - 1] + 1;
for (int i = 1; i <= n; ++i)
cout << ar[veNum[i] - 1];
cout << endl;
if (veNum[1] >= iAllLen - n + 1)
break;
}
}
}
int main()
{
int ar[] = { 3, 5, 9, 1, 0, 5 };
int iAllLen = sizeof(ar) / sizeof(ar[0]);
int n = 3;
allprint(ar, iAllLen, n);
return 0;
}
--------------------------------------------------------------------------優雅分界線-------------------------------------------------------------------------------
約瑟夫環問題:
m個士兵,因為被敵人包圍卻不想俘虜,決定報數決定生死。沒報數到3的人自殺,剩下的人繼續報數,求最後活下的兩個人。
//思路:新開闢一個空間 用於儲存
int nextpos(int ipos, int iRingNum, vector<int> &veNum)
{
ipos = ipos + 1 >= iRingNum ? 0 : ipos + 1;
while (ipos < iRingNum)
{
if (veNum[ipos] == 1)
ipos++;
else
return ipos;
if (ipos == iRingNum)
ipos = 0;
}
}
void printring(int iRingNum, int iLiveNum)
{
if (iRingNum <= 0 || iLiveNum <= 0 || iRingNum < iLiveNum)
return;
vector<int> veNum(iRingNum); //儲存的vector
int iAllNum = 0; //總體多少個
int iNum = 0; //對iLiveNum求餘之後下標
int j = 1;
for (int i = 0;;) //下標
{
j++;
i = nextpos(i, iRingNum, veNum);
if (j == iLiveNum) //要死的寶寶
{
veNum[i] = 1;
iAllNum++; //共死了多少個寶寶
if (iRingNum - iAllNum <= iLiveNum - 1) //存活的寶寶
break;
j = 0;
}
}
for (int i = 0; i < veNum.size(); ++i)
cout << veNum[i] << " ";
cout << endl;
}
int main()
{
int iRingNum = 0;
int iLiveNum = 0;
cin >> iRingNum;
cin >> iLiveNum;
printring(iRingNum, iLiveNum);
return 0;
}
全排列:
//全排列
/////////庫方法
int main()
{
int ar[] = { 1, 2, 3 };
int iLen = sizeof(ar) / sizeof(ar[0]);
do
{
for (int i = 0; i < iLen; ++i)
cout << ar[i];
cout << endl;
} while (next_permutation(ar, ar + iLen));
return 0;
}
/////////普通方法
void allprint(int ar[], int iLen, int iLeft)
{
if (iLeft >= iLen)
{
for (int i = 0; i <= iLen; ++i)
cout << ar[i];
cout << endl;
}
else
{
for (int i = iLeft; i <= iLen; ++i)
{
int iTmp = ar[iLeft];
ar[iLeft] = ar[i];
ar[i] = iTmp;
allprint(ar, iLen, iLeft + 1);
iTmp = ar[iLeft];
ar[iLeft] = ar[i];
ar[i] = iTmp;
}
}
}
void allprint(int ar[], int iLen)
{
if (ar == NULL || iLen <= 0)
return;
allprint(ar, iLen-1, 0);
}
int main()
{
int ar[] = { 1, 2, 3 };
int iLen = sizeof(ar) / sizeof(ar[0]);
allprint(ar, iLen);
return 0;
}
此致
敬禮