格雷码、全排列、约瑟夫环、m个元素中求n个元素的所有集合

格雷码:

格雷码是指,通过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;
}

此致

敬礼

猜你喜欢

转载自blog.csdn.net/zhanglu_1024/article/details/82951377
今日推荐