生成可重集的排列 hdu 1716 排列2

1、生成1~n的排列

void print_permutation(int n,int A*,int cur)
{
    if(cur==n)
    {
        for(int i=0;i<n;++i)
            if(i!=n-1) printf("%d ",A[i]);
        printf("\n");
    }
    else
    {
        for(int i=1;i<=n;++i)
        {
            if(vis[i]) continue;
            else
            {
                vis[i]=1;
                A[cur]=i;
                print_permutation(n,A,cur+1);
                vis[i]=0;
            }
        }
    }
}

2、生成可重集的排列

生成可重集的排列 hdu 1716 排列2

生成可重集的排列 hdu 1716 排列2

输出格式真的是太经典了emmm

//A,神奇的输出格式
#include<iostream>
#include<algorithm>
using namespace std;
int s[4];
int ans[4];
int flag=0,sign;
int sign1;
void dfs(int cur)
{
    if(cur==4)
    {
        if(flag!=ans[0])                //看看和上一个千位是否相同
        {
            if(flag)                    //不相同,但是若flag=0,说明是第一行,前面没用空行,否则有空行
              cout<<endl;
            flag=ans[0];                //记录上一个答案的千位
            sign=0;
        }
        ++sign;
       if(sign!=1) cout<<" ";
       for(int i=0;i<4;++i)
         cout<<ans[i];
    }
    else
    {
        for(int i=0;i<4;++i)
        {
            if(!i||s[i]!=s[i-1])                                //不重不漏地枚举
            {
                int c1=0,c2=0;
                for(int j=0;j<cur;++j) if(ans[j]==s[i]) c1++;   //已经使用掉的s[i]数量
                for(int j=0;j<4;++j) if(s[j]==s[i]) c2++;       //总共有的s[i]数量
                if(!cur)                                        //如果是千位数的首位
                {
                    if(!s[i]||c1==c2) continue;                 //是0或者没有位置了,告辞
                    ans[cur]=s[i];  //
                    dfs(cur+1);
                }
                else if(c1<c2)
                {
                    ans[cur]=s[i];
                    dfs(cur+1);
                }

            }
        }
    }
}
int main()
{
    sign1=0;
    while(cin>>s[0]>>s[1]>>s[2]>>s[3])
    {
        if(!s[0]&&!s[1]&&!s[2]&&!s[3])
            break;
        sign1++;
        if(sign1!=1) cout<<endl;        //每一个样例前面一个空行
        flag=0,sign=0;
        sort(s,s+4);
        dfs(0);
        cout<<endl;
    }
}


stl版本  ->记录上一个是啥以保证和上一个是否一样的思路经常用

每新换一行sign就更新,标记是否是该行的第一组

void perm()         //next_permutation函数生成的是不重复的集合
{
    do
    {
        if(!s[0]) continue;                     //千位是0,不OK
        if(flag!=s[0])
        {
            if(flag) cout<<endl;                //新的开头,新的一行
            flag=s[0];
            sign=0;
        }
        ++sign;
        if(sign!=1) cout<<' ';
        for(int i=0;i<4;++i) cout<<s[i];
    }while(next_permutation(s,s+4));
}
int main()
{
    sign1=0;
    while(cin>>s[0]>>s[1]>>s[2]>>s[3])
    {
        if(!s[0]&&!s[1]&&!s[2]&&!s[3])
            break;
        sign1++;
        if(sign1!=1) cout<<endl;        //每一个样例前面一个空行
        flag=0,sign=0;
        sort(s,s+4);
        perm();
       // dfs(0);
        cout<<endl;
    }
}