枚举排列

字典序排列:一个个的递归填充;

1:1-n的全排列

int n;
void permutation(int cur,int *A)
{
    if(cur==n)
    {
        for(int i=0;i<n;i++)
            printf("%d ",A[i]);
        printf("\n");
        return;
    }
    for(int i=1;i<=n;i++)
    {
        int ok=0;
        for(int j=0;j<cur;j++)   //判断前面是否出现过
            if(A[j]==i){
                ok=1;
                break;
            }
        if(ok==0)
        {
            A[cur]=i;
            permutation(cur+1,A);
        }
    }
}

2:可重集的全排列

int p[100];
int n;
void permutation(int cur,int *A)
{
    if(cur==n)
    {
        for(int i=0;i<n;i++)
            printf("%d ",A[i]);
        printf("\n");
        system("pause");
        return ;
    }
    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(p[i]==A[j]) c1++;
            for(int j=0;j<n;j++)
                if(p[j]==p[i]) c2++;
            if(c1<c2)
            {
                A[cur]=p[i];
                permutation(cur+1,A);
            }
        }
    }
}

int main()
{
    int A[100];
    p[0]=1;
    p[1]=2;
    p[2]=3;
    p[3]=3;
    p[4]=3;
    p[5]=4;
    p[6]=5;
    n=7;
    permutation(0,A);
    return 0;
}

时间: 2024-08-23 02:31:13

枚举排列的相关文章

蓝桥杯 2014本科C++ B组 六角填数 枚举排列

标题:六角填数 如图[1.png]所示六角形中,填入1~12的数字. 使得每条直线上的数字之和都相同. 图中,已经替你填好了3个数字,请你计算星号位置所代表的数字是多少? 请通过浏览器提交答案,不要填写多余的内容. 简单的枚举排列,只要提前将12个结点标号,来判断六个线段总和是否相等. 代码如下: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define MAXN 13 5 int num

poj 1270 Following Orders 枚举排列

题意: 给一个字符集和一些字符之间的小于关系,求字符集上的所有可能排列. 分析: 暴力枚举可以分为枚举子集,枚举排列,枚举组合,这题是个简单的枚举排列,枚举过程中用小于关系剪枝即可. 代码: //poj 1270 //sep9 #include <iostream> #include <algorithm> using namespace std; char vars[64],constraint[256],ans[64]; int g[128][128],vis[256]; in

ACM:回溯法,枚举排列

(一)生成1~n的排列 分析:用递归的思想解决:先输出所有以1开头的排列(这一步是递归调用),然后输出以2开头的排列(又是递归调用),接着是以3开头的排列......最后才是以n开头的排列. 伪代码: void print_permutation(序列A, 集合S) { if(S为空) 输出序列A: else 按照从小到大的顺序依次考虑S的每个元素v { print_permutation(在A的末尾填加v后得到的新序列,S-{v}): } } 下面是实现代码: #include <iostre

poj 2585 Window Pains 暴力枚举排列

题意: 在4*4的格子中有9个窗体,窗体会覆盖它之下的窗体,问是否存在一个窗体放置的顺序使得最后的结果与输入同样. 分析: 在数据规模较小且不须要剪枝的情况下能够暴力(思路清晰代码简单),暴力一般分为枚举子集(for(s=0;s<1<<n;++s))和枚举排列(next_permutation). 代码: //poj 2585 //sep9 #include <iostream> #include <algorithm> using namespace std;

枚举排列 之 “生成1~n的排列”

一.原题 输入n之后,生成1~n的排列. (题目来源:<算法竞赛入门经典>[刘汝佳]) 二.题目源代码 #include <stdio.h> #define MAXN 1000 int a[MAXN][MAXN]; void print_permutation(int n,int*a,int cur) { int i,j; if(cur==n) //递归边界 { for(i=0;i<n;i++) printf("%d",a[i]); printf(&quo

UVa 140 (枚举排列) Bandwidth

题意较复杂,请参见原题=_=|| 没什么好说的,直接枚举每个排列就好了,然后记录最小带宽,以及对应的最佳排列. STL里的next_permutation函数真是好用. 比较蛋疼的就是题目的输入了.. 还有就是不明白,为什么19.20行注释哪错了?? 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 10; 5 6 int id[256], letter[maxn]; 7 char in[1000];

DFS之枚举排列组合

枚举可重复排列的模板 #include<iostream> using namespace std; int n,m,ans[15]; int a[15];//待排列的数存储在此 bool vis[15]; void dfs(int cnt)//按字典序输出n个数选m个数的所有排列 { if(cnt==m) { for(int i=0;i<m;i++) cout<<ans[i]<<" "; cout<<endl; return ;

枚举排列模板、

1 //生成1~n的排列,按字典序由小到大排列 2 void print_permutation(int n,int* A,int cur) 3 { 4 if(cur==n){ //递归边界 5 for(int i=0;i<n;++i) printf("%d",A[i]); 6 printf("\n"); 7 } 8 else 9 for(int i=1;i<=n;++i){ //尝试在A[cur]中填各种数字i 10 int ok=1; 11 for(

UVa140 Bandwidth (枚举排列)

链接:http://acm.hust.edu.cn/vjudge/problem/19399分析:将结点字母用数字0~n-1表示,id[ch]将字符映射到对应的数字编号,letter将数字编号映射到对应的字符,用两个vector将每个结点的相邻结点编号存下来,然后枚举0~n-1位置上的结点编号,用pos记录每个结点编号所在的位置方便以后查找,然后就是遍历vector,第一个vector代表结点编号i,第二个vector代表结点i的相邻结点编号,找出最远距离,如果当前找到的最远距离已经大于或等于a

UVa 216 Getting in Line【枚举排列】

题意:给出n个点的坐标,(2<=n<=8),现在要使得这n个点连通,问最小的距离的和 因为n很小,所以可以直接枚举这n个数的排列,算每一个排列的距离的和, 保留下距离和最小的那个排列就可以了(这个地方和带宽那题有点像,用memcpy将整个排列保留下来) 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath> 5 #include<stack