38. 考古学家

126 阅读1分钟

题目描述

有一个考古学家发现一个石碑,但是很可惜,发现时其已经断成多段,原地发现n个断口整齐的石碑碎片。

为了破解石碑内容,考古学家希望有程序能帮忙计算复原后的石碑文字组合数,你能帮忙吗?

输入描述

第一行输入 n

  • n表示石碑碎片的个数

第二行依次输入石碑碎片上的文字内容s,共有n组。 

输出描述

输出石碑文字的组合(按照升序排列),行末无多余空格。

备注

如果存在石碑碎片内容完全相同,则由于碎片间的顺序变换不影响复原后的碑文内容,即相同碎片间的位置变换不影响组合。

用例

输入:
3 
a b c

输出:
abc  
acb  
bac  
bca  
cab  
cba

说明:
当石碑碎片上的内容为“a”,“b”,“c”时,则组合有“abc”,“acb”,“bac”,“bca”,“cab”,“cba
输入:
3 
a b a

输出:
aab  
aba  
baa

说明:
当石碑碎片上的内容为“a”,“b”,“a”时,则可能的组合有“aab”,“aba”,“baa
输入:
3 
a b ab

输出:
aabb  
abab  
abba  
baab  
baba

说明:
当石碑碎片上的内容为“a”,“b”,“ab”时,则可能的组合有“aabb”,“abab”,“abba”,“baab”,“baba

代码

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;

int n;
vector<string> arr;

void dfs(vector<bool>& used, const string& path, int level, set<string>& res)
{
	if (level == n)
	{
		res.insert(path);
		return;
	}

	for (int i = 0; i < n; i++)
	{
		if (used[i]) continue;

		if (i > 0 && arr[i] == arr[i - 1] && !used[i - 1]) continue;

		used[i] = true;
		dfs(used, path+arr[i], level + 1, res);
		used[i] = false;
	}
}

int main()
{
	cin >> n;

	for (int i = 0; i < n; i++)
	{
		string temp;
		cin >> temp;
		arr.push_back(temp);
	}

	sort(arr.begin(), arr.end());

	vector<bool>used(n, false);
	set<string>res;
	dfs(used,"", 0, res);
	// 输出石碑文字的组合(按照升序排列)
	for (const auto& item : res) {
		cout << item << endl;
	}

	return 0;
}