回溯求解排列组合(求源码评论区留言)

回溯求解排列组合的关键在于两点:
一是要明白回溯的思想到底是什么
二是要考虑清楚什么时候进行向下探索,什么时候碰壁回头,什么时候到达回溯的重点,退出循环。也就是回溯过程中的约束条件

回溯思想:向前走,碰壁回头
回溯的一般形式如下:
回溯形式
以求解排列A(n,m)为例,这里解释一下排列的约束条件:
1.第一个约束条件就是选出的数不一样。
2.每一个数都小于等于n。
3.选够m个数即进行输出。
4.向下探索,向上回溯。

至于组合,只需要在排列的第一个条件上加上一个固有的顺序要求就o了。

运行截图:
jieguo
源码这里暂时不予给出,有需要的话,可以评论区留下自己的邮箱。(因为是作业,害怕自己出现类同代码。)

预计11月底,进行给出。

二更:
源码附上:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
//求解A(n,m); 
void PaiLie(int m,int n);    //排列
void ZuHe(int m,int n);      //组合 
int main()
{
	int m,n;
	cout<<"Input n m:";
	cin>>n>>m;
	PaiLie(n,m);
	ZuHe(n,m);
}

void PaiLie(int m,int n)     //排列        A(m,n)
{
	int a[100]={0};
	int i=1;
	int count=0;            //计算总长度 
	a[i]=1;
	while(1)
	{
		int flag=1;
		for(int j=1;j<i;j++)      
		{
			if(a[i]==a[j])              //不满足约束条件,标志位置零 
			{
				flag=0;
			    break;
			}
		}
		
		if(flag&&i<n)                  //向下探索 
		{
			i++;
			a[i]=1;
			continue;
		} 
		
		if(flag&&i==n)                //满足条件进行输出 
		{
			for(int j=1;j<=n;j++)
			{
				if(j<n)
				{
					cout<<a[j]<<",";
				}
				if(j==n)
				{
					cout<<a[j]<<endl;
				} 
			}
			count++;
		}
		
		while(a[i]==m&&i>1)              //向上回溯 
		{
			i--;
		}
		
		if(i==1&&a[i]==m)                //回溯到头了,退出循环 
		{
			break;
		}    
		else                             //本阶段继续探索 
		{
			a[i]++;
		}
	}
	cout<<"回溯 排列个数:"<<count<<endl; 
} 
void ZuHe(int m,int n)      //组合 
{
	int a[100]={0};
	int i=1;
	int count=0;
	a[i]=1;
	while(1)
	{
	   int flag=1;
	   for(int j=1;j<i;j++)          
	   {	
	      if(a[i]>=a[j])     //不满足约束条件,标志位清零 
	      {
	      	flag=0;
	      	break;
		  }
	   }
	   
	   if(flag&&i<n)        //数量不够,继续向下探索 
	   {
	   	  i++;
		  a[i]=1;
		  continue; 
	   }
	   
	   if(flag&&i==n)      //满足条件,进行输出 
	   {
	   	  for(int j=1;j<=n;j++)
	   	  {
	   	  	if(j<n)
	   	  	{
	   	  		cout<<a[j]<<",";
	   	  	}
	   	  	if(j==n)
	   	  	{
	   	  		cout<<a[j]<<endl;
		    }
	   	  }
	   	  count++;
	   }
	   
	   while(a[i]==m&&i>1)    //向上回溯 
	   {
	   	  i--;
	   }
	   
	   if(a[i]==m&&i==1)     //回溯到头,退出回溯 
	   {
	   	 break; 
       }
       else
       {
       	 a[i]++;             //在当前阶段继续回溯 
	   }
	} 
	cout<<"回溯 组合个数:"<<count<<endl;
}

借宿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值