C++ P2830 生成可重集的排列(算法竞赛P185)

//直接在P1183的基础上做几处改动;

#include<iostream>
#include<cstdio>
using namespace std;

int p[15],n,m;
int sign[15],ap[15];//标记数组;
void outans()//输出函数
{
  for(int i=1;i<=m;i++) printf("%d ",p[i]);
  printf("\n");
  return;
}
void DFS(int x)//往第x位上面放数字;
{
  if(x>m){outans();return;}
  for(int i=1;i<=10;i++)
  {
    if(ap[i]<sign[i])
    {
      ap[i]++;p[x]=i;
      DFS(x+1);
      ap[i]--;//一定做到回溯,消除痕迹;
    }
  }
}
int main()
{
  scanf("%d%d",&n,&m);
  int x;
  for(int i=1;i<=n;i++)
  {
    scanf("%d",&x);
    sign[x]++;//初始化集合,记录每个元素的出现次数;
  }
  DFS(1);//生成所有符合条件的排列;
  return 0;
}

时间: 2024-12-16 10:10:19

C++ P2830 生成可重集的排列(算法竞赛P185)的相关文章

生成可重集的排列

下面给出自己编写的代码: 1 #include<stdio.h>  2 int P[100],A[100];   3 void print_permutation(int n,int* P,int* A,int cur)  4 {    5 int i, j;  6 if(cur == n)  7 {  8 for(i = 0; i < n; i++)  9 printf("%d ", A[i]);      10 printf("\n");  1

生成可重集的排列(方法)

通过暴力或者dfs的方法可以很容易地得到n个数的全排列,可生成可重集的呢,例如给出一个数组a[],要求输出这个数组的全排列,与普通的求全排列不同,数组中很可能存在重复的数,所以方法都需要改一改: DFS #include"iostream"#include"cstring"#include"cstdio"using namespace std;int n,book[21],a[21];int ca=1; void dfs(int step){if

枚举生成可重集的排列

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int N=1e3+10;int a[N],p[N];void print_permutation(int n,int *p,int *a,int cur){ int i,j; if(cur==n) { for(i=0; i<n; i++) printf("%d ",a[i]); pri

算法入门经典-第七章 例题7-2-2 可重集的排列

可重:如果问题变成输入数组p,并按字典序输出数组A个元素的所有全排列,则需要修改代码集的全排列 // Rujia Liu #include<cstdio> #include<algorithm> using namespace std; int P[100], A[100]; // 输出数组P中元素的全排列.数组P中可能有重复元素 void print_permutation(int n, int* P, int* A, int cur) { if(cur == n) { for(

生成可重集的排序 (白书P184)

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int ans[6]; int book[6],a[6],n; void dfs(int cnt) { int i,j; if(cnt==n) { for(i=0;i<n;i++) if(!i) printf("%d",ans[i]); else

C++ P2832 生成可重集的子集

#include<iostream>#include<cstdio>using namespace std; int n,m,vis[15],num[15];//vis[i]代表数字i在全集中出现的总次数,num[i]为i在子集中出现的次数: void data_in(){ scanf("%d%d",&n,&m); int x; for(int i=1;i<=n;i++) { scanf("%d",&x); vi

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

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 =

POJ 1256 Anagram(输入可重集枚举排序)

[题意简述]:本题题意很好理解!题目给出的Hint,使我们对关键点有了更加清晰的认识 An upper case letter goes before the corresponding lower case letter. So the right order of letters is 'A'<'a'<'B'<'b'<...<'Z'<'z'. 就是给一个序列(序列可以有重复的元素),让我们输出它的所有排列,字母顺序规定给出! [分析]:这道题是我之前学习枚举排序和子

生成排列算法

1.递归方法 例如,如果集合是{1,2,3},那么这个集合中元素的所有排列是{(1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,1,2),(3,2,1)},显然,给定n个元素共有n!种不同的排列,如果给定集合是{1,2,3,4},可以用下面给出的简单算法产生其所有排列,即集合(1,2,3,4)的所有排列有下面的排列组成: (1)以1开头后面跟着(2,3,4)的排列 (2)以2开头后面跟着(1,3,4)的排列 (3)以3开头后面跟着1,2,4)的排列 (4)以4开头后面跟着(1