Codeup 问题 A: 全排列(入门)

题目链接:点击这里

Codeup 问题 A: 全排列(入门)_第1张图片

考虑 N = 3 N=3 N3 ,代表了有 A ,   B ,   C A, \ B,\ C A, B, C 三个空位置和写有 1 ,   2 ,   3 1,\ 2, \ 3 1, 2, 3 的卡片,我们需要将卡片放到空位置上,并且每个位置只能放一张卡片,现在我们需要找出这 3 3 3 张卡片的所有不同摆放方法。

在某一个位置,考虑应该先放哪张卡片的时候,我们可以约定一个先后顺序 1 → 2 → 3 1 \rightarrow 2 \rightarrow 3 123

根据约定顺序放置卡片,首先可以得到: A ( 1 ) A(1) A(1) B ( 2 ) B(2) B(2) C ( 3 ) C(3) C(3),这时我们已经得到了一种全排列 ( 1 , 2 , 3 ) (1, 2, 3) (1,2,3)。而现在我们实际上已经走到了一个并不存在的位置D(即结束位置,但是我们排列并没有结束)。

现在我们需要立即回到位置 C C C,取回卡片 3 3 3,然后尝试是否还能放入其它卡片(当然是按照我们的约定顺序),结果显然是我们手里并没有其它可以放入的卡片。

所以,我们需要继续回退一步来到位置 B B B,取出卡片 2 2 2,然后继续尝试是否能放入其它卡片(当然是按照我们的约定顺序),这时我们发现可以放入卡片 3 3 3;放入卡片 3 3 3 后,我们向前一步来到位置 C C C,尝试放入卡片(当然是按照我们的约定顺序),这时我们发现可以放入卡片 2 2 2;放完卡片 2 2 2,我们继续向前一步来到了并不存在的位置 D D D;这时我们得到了另一种全排 ( 1 , 3 , 2 ) (1, 3, 2) (1,3,2)

… …

按照上述步骤重复下去,就可以得到所有的全排列。

补充:如果要求结果是递增输出,在下面代码上加一句代码i > ans[x]即可(剪枝)。

#include
#include
#include
#include

using namespace std;

int ans[11];
bool vis[11];
int n;

void dfs(int x)
{
	if(x == n + 1)   				//如果到了不存在的位置,就打印退出
	{
		for(int i = 1; i <= n; i++)	//打印
		{
			cout<<ans[i];
			if(i < n)	cout<<" ";
		}
		cout<<endl;
		return;  					//需要回退到调用处
	}
	
	for(int i = 1; i <= n; i++)		//有1~n个数(卡片)可选
	{
		if(vis[i] == false)			//如果该数(卡片)还没有被使用
		{
			ans[x] = i;				//将该数(卡片)放到位置上
			vis[i] = true;			//标记为已使用
			dfs(x + 1);				//执行下一步,在下一个位置再次执行
			vis[i] = false;			//将尝试过的数(卡片)收回
		}
	}
}

int main()
{
	cin>>n;
	dfs(1);
	return 0;
}

你可能感兴趣的:(DFS及其剪枝)