有关next_permutation()函数的用法, poj 2718

之前接触过一次next_permutation函数,今天做的时候又忘记怎么用了。- -

这是一个c++函数,包含在头文件<algorithm>里面,下面是基本格式。

int a[];
do{
    
}while(next_permutation(a,a+n));
下面的代码可产生1~n的全排列。

#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        if(!n) break;
        int a[1000];
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        sort(a,a+n);//可以自行测试一下删除后的结果
        do{
            for(int i=0;i<n;i++)
                printf("%d ",a[i]);
            printf("\n");
        }while(next_permutation(a,a+n));
    }
    return 0;
}

注意到代码的第12行,利用了一个sort()将数组a里面的元素从小到大排序了一遍。

那么如果不排序的话会是如何呢?

例如输入

3

1 0 2

如果有sort()

输出为

0 1 2
0 2 1
1 0 2
1 2 0
2 0 1
2 1 0

若无

则输出为

1 0 2
1 2 0
2 0 1
2 1 0

可以发现少了许多种组合方法。

不过,仔细比较各种组合方法和有无sort()的输出,可以发现函数next_permutation()是按照字典序产生排列的,并且是从数组中当前的字典序开始依次增大直至到最大字典序

下面2题可利用next_permutation()直接求解。

POJ 2718

题意:给出几个数,分为2个集合,每个集合中的数字可构成一个数,则求这两个集合构成的数的差的最小值。

思路:利用next_permutation()枚举所有数字。当确定总共有几个数时,就已经确定了那两个数的位数,当然是越接近越好。

#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
int main(){
    int ca;
    scanf("%d",&ca);
    getchar();
    for(int cc=0;cc<ca;cc++){
        int a[11],num=0,ans=0x3f3f3f3f;
        char s[1000];
        gets(s);//因为不知道有几个数字,只知道都在一行输入
        for(int i=0;i<strlen(s);i++){
            if(s[i]>='0'&&s[i]<='9')
                a[num++]=s[i]-'0';
        }
        sort(a,a+num);
        do{
            int num1=0,num2=0,te=1;
            if((!a[num/2-1]||!a[num-1])&&num>2)
                continue;
            for(int i=0;i<num/2;i++){
                num1+=te*a[i];
                te*=10;
            }
            te=1;
            for(int i=num/2;i<num;i++){
                num2+=te*a[i];
                te*=10;
            }
            ans=min(ans,abs(num1-num2));
        }while(next_permutation(a,a+num));
        printf("%d\n",ans);
    }
    return 0;
}


POJ 3187

题意:输入n和sum,n代表有最后数字的范围是在1~n,sum是操作后的总和。操作类似于杨辉三角,比如输入4 16则应该输出3 1 2 4

因为  3  1 2  4

            4  3  6

              7  9

               16

思路:枚举1~n的所有排列,直至有一种排列使得最后结果为sum就结束。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        int a[11],b[11];
        for(int i=0;i<n;i++)
            a[i]=i+1;
        do{
            for(int i=0;i<n;i++)
                b[i]=a[i];//因为不能改变数组a中的值,所以需要把数组a的值复制给数组b
            int nn=n;
            while(nn>1){
                for(int j=0;j<nn-1;j++)
                    b[j]=b[j]+b[j+1];
                nn--;
            }
            if(b[0]==m)
                break;
        }while(next_permutation(a,a+n));
        for(int i=0;i<n-1;i++)
            printf("%d ",a[i]);
        printf("%d\n",a[n-1]);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值