暴力搜索专题小结:全排列及可重集排列生成算法

1~n的全排列

(1)思路:按照递归的思想,初始化集合S中含有1~n所有元素。如果1~n的集合S为空,那么输出全排列;否则从小到大依次考虑每个元素i,在A的末尾添加i后,集合S变为S-{i}。这里我们不需要集合S,只需要利用一个变量cur表示当前位要填的数即可。那么A中没有出现过的元素均可以选择。

#define N 100
int A[N];
void print_permutation(int n, int*A, int cur)
{
	if (cur == n)
	{
		for (int i = 0; i < n; i++)
			printf("%d ", A[i]);
		printf("\n");
	}
	else for (int i = 1; i <= n; i++)
	{
		int ok = 1;
		for (int j = 0; j < cur;j++)
		if (A[j] == i){ ok = 0; break; }
		if (ok)
		{
			A[cur] = i;
			print_permutation(n, A, cur + 1);
		}
	}
}

可重集的排列

如果将上述问题改为“输入数组P,按照字典序输出P中元素的所有排列”,注意这里P数组中的元素可以重复。那么这时方法大体上类似于全排列,不过一些细节需要变动:

(1)首先要为P数组排序,然后再调用print_permutation函数;

(2)由于P数组中元素可以重复出现,因此要检查在cur位之前有几个元素P[i],假设有c1个,而P数组中总共有c2个,那么此时可以选择;

(3)由于P数组中元素可以重复出现,但枚举时不应当重复枚举,因此还要检查P的第一个元素和所有“与前一个元素不相同”的元素。

#define N 100
int A[N];
int P[N];
void print_permutation(int n, int*P, int*A, int cur)
{
	if (cur == n)
	{
		for (int i = 0; i < n; i++)
			printf("%d ", A[i]);
		printf("\n");
	}
	else for (int i = 0; i < n; i++)//枚举每一个位置
	if (!i || P[i] != P[i-1])//注意元素不能重复枚举
	{
		int c1 = 0, c2 = 0;
		for (int j = 0; j < cur; j++)if (A[j] == P[i])c1++;
		for (int j = 0; j < n; j++)if (P[j] == P[i])c2++;
		if (c1<c2)
		{
			A[cur] = P[i];
			print_permutation(n, P, A, cur + 1);
		}
	}
}
时间: 2024-10-29 19:07:47

暴力搜索专题小结:全排列及可重集排列生成算法的相关文章

搜索专题小结及例题:POJ2251&amp;POJ1426&amp;POJ3087&amp;POJ2488

图的遍历也称为搜索,就是从图中某个顶点出发,沿着一些边遍历图中所有的顶点,且每个顶点仅被访问一次,遍历可采取两种不同的方式:深度优先搜索(DFS)和广度优先搜索(BFS). 1.DFS算法思想` 从顶点v出发深度遍历图G的算法 ① 访问v0顶点,置vis[v0]=1,搜索v0未被访问的邻接点w,若存在邻接点w,则dfs(w),直到到达所有邻接点都被访问过的顶点u为止,接着退回一步,看是否还有其他没有被访问的邻接点.如果有,则访问此顶点,进行前述类似的访问,如果没有,就在退回一步进行搜索,重复上述

搜索专题小结:迭代加深搜索

迭代加深搜索 迭代加深搜索(Iterative Deepening Depth-First Search, IDDFS)经常用于理论上解答树深度上没有上界的问题,这类问题通常要求出满足某些条件时的解即可.比如在"埃及分数"问题中要求将一个分数a/b分解成为若干个形如1/d的加数之和,而且加数越少越好,如果加数个数相同,那么最小的分数越大越好.下面总结一下该方法的一般流程: (1)概述:迭代加深搜索是通过限制每次dfs的最大深度进行的搜索.令maxd表示最大的搜索深度,那么dfs就只能在

搜索专题总结

搜索专题总结 第七章的例题做得差不多了,还有一道枚举二叉树和一道比较难的搜方块的没过,另外有一道火柴的用IDA*水过,并没有过大数据,由于这道可以用dancing links过,所以留着dancing links一坑.接下来总结下这章的收获,首先最重要的当然是不需要判重的高效率的IDA*以及估价函数的设计技巧:然后是bfs+hash写得更熟练了,如果hash需要erase那么就只能用指针版的,但是效率会很慢,否则就用数组版的. 做搜索题的几个要点: 1,估算最坏复杂度. 2,寻找合适的剪枝策略,

01背包 暴力搜索

/** 01背包,recursive * 05.08/2014 */ #include <cstdio> #include <cstring> #include <algorithm> #define MAXN 30000 using namespace std; int N,W; int w[MAXN],v[MAXN]; int solve(int i, int tw) { int res; if( i == N) //已经全部搜索完 res = 0; else if

hdu 1427 速算24点 dfs暴力搜索

速算24点 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description 速算24点相信绝大多数人都玩过.就是随机给你四张牌,包括A(1),2,3,4,5,6,7,8,9,10,J(11),Q(12),K(13).要求只用'+','-','*','/'运算符以及括号改变运算顺序,使得最终运算结果为24(每个数必须且仅能用一次).游戏很简单,但遇到无解的

搜索专题

搜索专题 标签(空格分隔): ACM专题小结 搜索专题主要就是围绕dfs()和bfs(). 这两个函数其实不难,搜索可以解决很多最小路径,最少次数问题bfs()等问题 维数从一维到三维:主要抓住移动的方向的控制,以及对访问过的状态的标记,以免重复访问,重复访问一方面运行时间加长另一方面申请的空间也会无厘头的暴增. 曾经在刷一道题的时候,系统显示的使用空间远远大于定义变量的空间,一时间懵逼了,后来才发现是标记没处理好,导致了大量的重复访问. 还有一个要注意的地方就是队列的清空,或者在函数里面定义队

[暴力搜索] POJ 3087 Shuffle&#39;m Up

Shuffle'm Up Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10003   Accepted: 4631 Description A common pastime for poker players at a poker table is to shuffle stacks of chips. Shuffling chips is performed by starting with two stacks o

HDU 3699 A hard Aoshu Problem (暴力搜索)

题意:题意:给你3个字符串s1,s2,s3;要求对三个字符串中的字符赋值(相同的字符串进行相同的数字替换), 替换后的三个数进行四则运算要满足左边等于右边,求有几种解法. Sample Input 2 A A A BCD BCD B Sample Output 5 72 eg:ABBDE   ABCCC   BDBDE :令 A = 1, B = 2, C = 0, D = 4, E = 5 12245 + 12000 = 24245: 注意没有前导零!! #include<stdio.h>

HDU 4499 Cannon (暴力搜索)

题意:在n*m的方格里有t个棋子,问最多能放多少个炮且每个炮不能互相攻击(炮吃炮) 炮吃炮:在同一行或同一列且中间有一颗棋子. #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <math.h> #define M 50 #define LL long long using