搜索与回溯:有重复元素的排列问题

【题目描述】

设R={ r1, r2 , …, rn}是要进行排列的n个元素。其中元素r1, r2 , …, rn可能相同。试设计一个算法,列出R的所有不同排列。

给定n 以及待排列的n 个元素。计算出这n 个元素的所有不同排列。

输入

输入数据。第1 行是元素个数n,1≤n≤500。接下来的1 行是待排列的n个元素。

输出

计算出的n个元素的所有不同排列输出中。输出最后行的数是排列总数。

样例

【输入】


aacc

【输出】 

aacc 
acac 
acca 
caac 
caca 
ccaa 
6

【参考代码】 

#include<bits/stdc++.h>
using namespace std;
char a[251];
int n[27],s,sum=0;
void f(int k) {
	if(k==s+1) {
		for(int i=1;i<=s;i++)
			printf("%c",a[i]);
		printf("\n");
		sum++;
		return ;
	}
	for(int i=1;i<=26;i++)//从字母a找到字母z 
	{
		if(n[i]!=0)
		{
			n[i]--;
			a[k]=char(i+96);
			f(k+1);//下一个字符 
			n[i]++;
		}
		else
			continue;
	}
}
int main() {
	scanf("%d",&s);
	for(int i=1; i<=s; i++) {
		cin>>a[i];
		n[a[i]-96]++;//每个字符的数量
	}
	f(1);
	printf("%d",sum);
	return 0;
}

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回溯法是一种常用于解决组合问题算法,可以用来解决子集和全排列问题。 对于子集和问题,可以使用回溯法来求解。具体步骤如下: 1. 定义一个数组来存储当前的子集,初始为空集。 2. 从原始数组的第一个元素开始,依次将元素加入到当前的子集中,并计算子集的和。 3. 如果子集的和等于目标和,则将当前的子集加入到结果集中。 4. 如果子集的和小于目标和,则继续向下搜索,将下一个元素加入到子集中。 5. 如果子集的和大于目标和,则回溯到上一个元素,将其从子集中删除,并继续向下搜索。 6. 如果已经搜索到原始数组的最后一个元素,且子集的和不等于目标和,则回溯到上一个元素,将其从子集中删除,并继续向下搜索。 7. 重复步骤2到步骤6,直到搜索完所有的子集。 对于全排列问题,也可以使用回溯法来求解。具体步骤如下: 1. 定义一个数组来存储当前的排列,初始为空。 2. 从原始数组的第一个元素开始,依次将元素加入到当前的排列中。 3. 如果当前的排列长度等于原始数组的长度,则将当前的排列加入到结果集中。 4. 如果当前的排列长度小于原始数组的长度,则继续向下搜索,将下一个元素加入到排列中。 5. 如果当前的排列中已经包含了某个元素,则回溯到上一个元素,将其从排列中删除,并继续向下搜索。 6. 如果已经搜索到原始数组的最后一个元素,且当前排列长度不等于原始数组的长度,则回溯到上一个元素,将其从排列中删除,并继续向下搜索。 7. 重复步骤2到步骤6,直到搜索完所有的排列。 需要注意的是,在回溯过程中,需要维护一个访问数组,用来记录哪些元素已经被访问过,避免重复访问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值