HDOJ 1716 排列2(next_permutation函数)

Stella981
• 阅读 710

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
3年前
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
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
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
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
京东云开发者 京东云开发者
5个月前
AIGC系统中聊天小助手卡片小组件嵌套设计实践
1.项目描述领航者卡片样式较多,有些卡片比较近似;可以用嵌套方案,实现一个卡片,多个子单元可拔插组件式卡片。2.逻辑设计2.1卡片示例聊天框提示3通用提示卡片设计通用卡片中加载//卡片组件unit加载...if(!options?.dataType)if(