【暴力入门】排列与组合枚举

排列和组合枚举都是暴力基础啦,虽然很简单但是总结一下比较好


组合

先从简单的说起吧,比如说从n个数里选k个

先放代码:

void combination(int cur,int cnt)//cur为当前数,cnt为已选择数的个数 
{  
    if(cnt==k) return ;  
    for(int i=cur;i<=n;i++)
    {  
        dfs(i+1,cnt+1);  
    }  
}  
conbination(1,0);

(这里的n, k, cur, cnt均指序号)

这种思路并不难理解,要保证每一位数前面都没有出现,可以直接从小到大,每一位都枚举上一位后面的数,通过递归就能把所有的组合都枚举出来啦。


排列

最准确的排列算法是通过一步步进化来的

Again,比方说从n个数里选出k个进行排列

最傻白甜的一个写法:

bool check(int i,int n)
{
	for(int j=1;j<n;j++)
	{
		if(a[j]==i) return false;
	}
	return true;
}

void permutation(int cnt)
{
	if(cnt==k+1) return ;
	for(int i=1;i<=n;i++)
	{
		if(check(i,cnt)) 
		{
			a[cnt]=i;
			permutation(cnt+1);
		}
	}
}

permutation(1);

通过前面的数字检查有没有重复,来实现每一次枚举不同的数。

然而这种写法是建立在原数组中本身没有重复数字的先决条件下的,但如果有重复的数字就gg了。

比如{1,2,3,4}可以但{1,1,3,4}不行


所以我们会想到开一个计数器Ci,记录每个数字一共出现了几次。

然后这样:

bool check(int i,int n,int c1)
{
	int c2;
	for(int j=1;j<n;j++)
	{
		if(a[j]==i) c2++;
	}
	if(c1>c2) return true;
	if(c1<=c2) return false;
}

void permutation(int cnt)
{
	if(cnt==k+1) return ;
	for(int i=1;i<=n;i++)
	{
		if(check(i,cnt,c[i])) 
		{
			a[cnt]=i;
			permutation(cnt+1);
		}
	}
}
挺麻烦的,但是能做对


但是,如果去考试的话,C++里其实有库可以直接用...

一个叫next_permutation的神奇函数

这时我们假设将要排列枚举的数组为P

#include<iostream>
#include<algorithm>//算法头文件
using namespace std;

int main()
{
	/*输入就不写了*/ 
	sort(p+1,p+n+1);    //需要从小到大排列时要先排序
	do{
		//对当前排列的顺序操作 
	} while(next_permutation(p+1,p+n+1));
	return 0;
} 
(还有这种操作???.jpg)


猜你喜欢

转载自blog.csdn.net/maxmeansmaximum/article/details/80919420
今日推荐