HDOJ 1716 排列2(next_permutation函数)

Stella981
• 阅读 534

Problem Description
Ray又对数字的列产生了兴趣:
现有四张卡片,用这四张卡片能排列出很多不同的4位数,要求按从小到大的顺序输出这些4位数。

Input
每组数据占一行,代表四张卡片上的数字(0<=数字<=9),如果四张卡片都是0,则输入结束。

Output
对每组卡片按从小到大的顺序输出所有能由这四张卡片组成的4位数,千位数字相同的在同一行,同一行中每个四位数间用空格分隔。
每组输出数据间空一行,最后一组数据后面没有空行。

Sample Input
1 2 3 4
1 1 2 3
0 1 2 3
0 0 0 0

Sample Output
1234 1243 1324 1342 1423 1432
2134 2143 2314 2341 2413 2431
3124 3142 3214 3241 3412 3421
4123 4132 4213 4231 4312 4321

1123 1132 1213 1231 1312 1321
2113 2131 2311
3112 3121 3211

1023 1032 1203 1230 1302 1320
2013 2031 2103 2130 2301 2310
3012 3021 3102 3120 3201 3210

这是一个求一个排序的下一个排列的函数,可以遍历全排列,要包含头文件
下面是以前的笔记    与之完全相反的函数还有prev_permutation
(1) int 类型的next_permutation
int main()
{
 int a[3];
a[0]=1;a[1]=2;a[2]=3;
 do
{
cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;//输入a[0],a[1],a[2];
} while (next_permutation(a,a+3)); //参数3指的是要进行排列的长度
//如果存在a之后的排列,就返回true。如果a是最后一个排列没有后继,返回false,每执行一次,a就变成它的后继
}
输出:
 1 2 3
 1 3 2
 2 1 3
 2 3 1
 3 1 2
 3 2 1
如果改成 while(next_permutation(a,a+2));
则输出:
 1 2 3
 2 1 
只对前两个元素进行字典排序
显然,如果改成 while(next_permutation(a,a+1)); 则只输出:1 2 3
若排列本来就是最大的了没有后继,
则next_permutation执行后,会对排列进行字典升序排序,相当于循环
 int list[3]={
  
  
  3,2,1};
next_permutation(list,list+3);
cout<<list[0]<<" "<<list[1]<<" "<<list[2]<<endl;
//输出: 1 2 3

例题:
Problem B

Ray又对数字的列产生了兴趣:
现有四张卡片,用这四张卡片能排列出很多不同的4位数,
要求按从小到大的顺序输出这些4位数。

Input
每组数据占一行,代表四张卡片上的数字(0<=数字<=9),
如果四张卡片都是0,则输入结束。

Output
对每组卡片按从小到大的顺序输出所有能由这四张卡片组成的4位数,
千位数字相同的在同一行,同一行中每个四位数间用空格分隔。
每组输出数据间空一行,最后一组数据后面没有空行。

Sample Input
1 2 3 4
1 1 2 3
0 1 2 3
0 0 0 0

Sample Output
1234 1243 1324 1342 1423 1432
2134 2143 2314 2341 2413 2431
3124 3142 3214 3241 3412 3421
4123 4132 4213 4231 4312 4321

1123 1132 1213 1231 1312 1321
2113 2131 2311
3112 3121 3211

1023 1032 1203 1230 1302 1320
2013 2031 2103 2130 2301 2310
3012 3021 3102 3120 3201 3210


#include < iostream >
#include < stdio.h >
#include < algorithm>
#include < string.h>
using namespace std;

int main()
{
    int a[5],i,j,k,m=0;
    while(~scanf("%d%d%d%d",&a[1],&a[2],&a[3],&a[4]))
    {
        if(a[1]==0&&a[2]==0&&a[3]==0&&a[4]==0)
            return 0;
        if(m)
            printf("\n");
        m=1;
        k=1;int h;
        do
        {
            if(a[1]==0)
                continue;
            if(k==1)
            {
                printf("%d%d%d%d",a[1],a[2],a[3],a[4]);
                k=0;
            }
            else
            {
            if(h==a[1])
                printf(" %d%d%d%d",a[1],a[2],a[3],a[4]);
            else
                printf("\n%d%d%d%d",a[1],a[2],a[3],a[4]);
            }
            h=a[1];
        }
        while(next_permutation(a+1,a+5));
        printf("\n");
    }
    return 0;
}

算法描述:

1、从尾部开始往前寻找 两个相邻 的元素

第1个元素i,第2个元素j(从前往后数的),且i<j

2、再从尾往前找第一个大于i的元素k。将i、k 对调

3、[j,last)范围的元素置逆( 颠倒排列 )

这个题目用递归也可以做:

#include < stdio.h>
#include < string.h>
#include < stdlib.h>
int a[6],vis[5],t,sol[5],last;
void dfs(int c)
{
    if(c==5)
    {
        if(sol[1]==0)
            return;    //千位是0的不符合
        if(t!=0 && sol[1]==last)
            printf(" ");  //一行的最后一个数后面不能输出空格
        if(t!=0 && sol[1]!=last)
        {
            printf("\n");   //千位不同则换行
        }
        last=sol[1]; //记录上一个的千位
        int j=1;
        for(j ;  j < = 4 ;  j++)
        {
            printf("%d",sol[j]);
        }
        t++;
    }
    int i;
    for(i = 1 ;  i <= 4 ;  i++)
    {
        if(vis[i]==0)
        {
            vis[i]=1;
            sol[c]=a[i];
            dfs(c+1);
            vis[i]=0;
            while(a[i]==a[i+1])    //关键: 去重复
                i++;    //因为题目的输入是从小到大(否则先排序),所以如果在一轮排列结束后
        }     //如果后一个将要被选的数与上一轮这个下标的数相同,则跳过
    }      //比如1 1 1 2,第一轮1 1 1 2,返回上一次dfs后sol[3]=2,sol[4]=1
}    //返回到c=2,此时a[2]==a[3]=1,若再选1则为1 1 1 2,跳过则为1 2 1 1
int main()
{
    int i,T=0;
    while(scanf("%d%d%d%d",&a[1],&a[2],&a[3],&a[4]))
    {
        if(a[1]==0&&a[2]==0&&a[3]==0&&a[4]==0) break;
        if(T!=0) printf("\n");
        T=1;
        memset(vis,0,sizeof(vis));
        t=0;
        dfs(1);
        printf("\n");
    }
    return 0;
}

本文同步分享在 博客“谙忆”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
2年前
typeScript数据类型
//布尔类型letisDone:booleanfalse;//数字类型所有数字都是浮点数numberletdecLiteral:number6;lethexLiteral:number0xf00d;letbinaryLiteral:number0b101
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
DaLongggggg DaLongggggg
3年前
python刷题-特殊回文数
问题描述  123321是一个非常特殊的数,它从左边读和从右边读是一样的。  输入一个正整数n,编程求所有这样的五位和六位十进制数,满足各位数字之和等于n。输入格式  输入一行,包含一个正整数n。输出格式  按从小到大的顺序输出满足条件的整数,每个整数占一行。样例输入52样例输出899998989989998899数据规模和约定 
DaLongggggg DaLongggggg
3年前
python刷题-01字串
问题描述对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能。它们的前几个是:0000000001000100001100100请按从小到大的顺序输出这32种01串。输出格式输出32行,按从小到大的顺序每行一个长度为5的01串。样例输出00000000010001000011<以下部分省略foriinrange(0
DaLongggggg DaLongggggg
3年前
python刷题-特殊的数字
问题描述  153是一个非常特殊的数,它等于它的每位数字的立方和,即153111555333。编程求所有满足这种条件的三位十进制数。输出格式  按从小到大的顺序输出满足条件的三位十进制数,每个数占一行。foriinrange(100,1000):astr(i)0bstr(i)1c
DaLongggggg DaLongggggg
3年前
python刷题-数列排序
资源限制时间限制:1.0s内存限制:512.0MB问题描述  给定一个长度为n的数列,将这个数列按从小到大的顺序排列。1<n<200输入格式  第一行为一个整数n。  第二行包含n个整数,为待排序的数,每个整数的绝对值小于10000。输出格式  输出一行,按从小到大的顺序输出排序后的数列。样例输入583649样例输出34689···
Wesley13 Wesley13
2年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
2年前
ImageMagick图像处理
合并图像dir命令行使用//示该目录下的所有文件名列表,并以A至Z字母顺序及数字顺序进行排列dir/o:ndir/o:n//按创建日期的顺序进行排列dir/o:ddir/o:d//按从小到大的顺序进行排列dir/o:sdir/o
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这