About next_permutation

来源:互联网 发布:淘宝定向投放 编辑:程序博客网 时间:2024/06/05 00:16

对于“下一个排列”,一开始不懂子集与搜索的概念,就穷举了好多种情况,发现了其中的规律

算法如下:

1. 对给定的排列,从右到左扫描各个字符,如果这些字符从右到左是按字典序递增的,该排列就是最后一个,没有下一个排列。

2. 从右到左扫描各个字符,如果第k个字符不是按字典序递增的,下一个排列可以将第k个字符增加一位后修改得到。

3.将第k个字符增加一位后,可能与该字符前缀中的字符重复,那就再增加一位,直到与前缀中的字符不重。

4.若第k个字符增加一位后,仅与该字符后缀中的字符重复,那就与后缀中重复的字符互换。

5.执行第4步后,保留前缀和新的第k个字符,将后缀的字符按字典序重新排列就得到原排列紧接的排列。

以下是代码实现:

char* next_permutation(char *str){    int t,m,temp;    int l=strlen(str);    for(int i=l-1; i>=0; i--)    {        if(str[i-1]<str[i])        {            t=i;            break;        }    }    if(t==0)        return NULL;    else    {        for(int i=l-1; i>=0; i--)        {            if(str[i]>str[t-1])            {                m=i;                break;            }        }        temp=str[t-1];        str[t-1]=str[m];        str[m]=temp;        for(int i=0; i<l-t; i++)        {            for(int j=l-1-i; j<l-1; j++)            {                if(str[j]>str[j+1])                {                    temp=str[j];                    str[j]=str[j+1];                    str[j+1]=temp;                }            }        }        return str;    }}
当然,也可以直接用STL库里的next_permutation函数,需要加头文件<algorithm>

附:题目

POJ  1731 - Orders(全排列)


#include <iostream>#include <cstring>#include <algorithm>using namespace std;int main(){    char a[10000];    while(cin>>a)    {        sort(a,a+strlen(a));        cout<<a<<endl;        while(next_permutation(a,a+strlen(a)))        {            cout<<a<<endl;        }    }    return 0;}

#include <iostream>#include <cstring>#include <algorithm>using namespace std;char* next_permutation(char *str){    int t,m,temp;    int l=strlen(str);    for(int i=l-1; i>=0; i--)    {        if(str[i-1]<str[i])        {            t=i;            break;        }    }    if(t==0)        return NULL;    else    {        for(int i=l-1; i>=0; i--)        {            if(str[i]>str[t-1])            {                m=i;                break;            }        }        temp=str[t-1];        str[t-1]=str[m];        str[m]=temp;        for(int i=0; i<l-t; i++)        {            for(int j=l-1-i; j<l-1; j++)            {                if(str[j]>str[j+1])                {                    temp=str[j];                    str[j]=str[j+1];                    str[j+1]=temp;                }            }        }        cout<<str<<endl;        next_permutation(str);    }}int main(){    char a[10000];    while(cin>>a)    {        sort(a,a+strlen(a));        cout<<a<<endl;        next_permutation(a);    }    return 0;}

UVa 10098 - Generating Fast


同样是全排列,只需注意输出换行,代码就不给出了


UVa 146 - ID Codes(下一个排列)


#include <iostream>#include <cstring>#include <algorithm>using namespace std;int main(){    char a[10000];    while(gets(a)!=NULL)    {        if(strcmp(s,"#")==0)break;        next_permutation(a,a+strlen(a));        cout<<a<<endl;    }    return 0;}

UVa 729 - The Hamming Distance Problem(二进制全排列)


#include <cstring>#include <algorithm>using namespace std;int main(){    char a[100];    int ncase,n,b;    cin>>ncase;    while(ncase--)    {        cin>>n>>b;        for(int i=0;i<n-b;i++)a[i]='0';        for(int i=n-b;i<n;i++)a[i]='1';        a[n]='\0';        while(next_permutation(a,a+strlen(a))        cout<<a<<endl;        if(ncase)cout<<endl;    }    return 0;}

#include <stdio.h>#include <stdlib.h>#include <string.h>void next(char *str){    int i,j,l,t,m,temp;    l=strlen(str);    for(i=l-1; i>=0; i--)    {        if(str[i-1]<str[i])        {            t=i;            break;        }    }    if(t==0)        return;    else    {        for(i=l-1; i>=0; i--)        {            if(str[i]>str[t-1])            {                m=i;                break;            }        }        temp=str[t-1];        str[t-1]=str[m];        str[m]=temp;        for(i=0; i<l-t; i++)        {            for(j=l-1-i; j<l-1; j++)            {                if(str[j]>str[j+1])                {                    temp=str[j];                    str[j]=str[j+1];                    str[j+1]=temp;                }            }        }        printf("%s\n",str);        next(str);    }}int main(){    char a[100];    int e,i,j,l,t,Case,n;    scanf("%d",&Case);    for(e=0; e<Case; e++)    {        scanf("%d%d",&l,&n);        for(i=0; i<l; i++)            a[i]='0';        for(i=l-1,j=0; j<n; j++,i--)            a[i]='1';            a[l]='\0';        puts(a);        next(a);        if(e<Case-1)        putchar('\n');    }    return 0;}