UVaOJ 146 - ID Codes


——by A Code Rabbit


Description

输入一个序列,要求你输出这些序列的下一个排列。


Types

Brute Force :: Elementary Skills


Analysis

下一个排列的意思是,把序列中的元素拿来做全排列。

然后排序所有的全排列序列。

下一个排列就是排序后当前序列所在下一个位置上的序列。


首先,我们要知道,全排列序列中最小的那个(或者说第一个),一定是元素从小到大有序的。

而全排列一个个数过去,一定是先后面的元素位置改变,才轮到前面的元素位置改变。

可以输出全排列序列,熟悉一下全排列序列的规律。


对于这道题,我们可以从后往前找,找到一个元素Ai,发现这个元素后面有比他大的元素中最小的元素Aj(可用二分搜索,因为Ai是从后往前一路找过来,第一个后面有比它大的元素的元素,所以它后面的序列必然有序)。

交换Ai和Aj两个元素的位置,一定可以得到一个比原来大的全排列。

那么,如何得到比原来全排列只大1的序列呢?

我们可以把元素Ai后面的序列排序。

这样,我们就可以得到比原全排列大的所有全排列中最小的那个。

那么就是我们要的,只比原来全排列大1的序列。

如果找不到这么一个Ai,就不存在下一个全排列。


当然,这题也可以偷偷懒,熟悉STL的同学一定知道有个next_permutation,这个函数的作用,恰好就是我们题目所要求的那样——求下一个全排列……

next_permutation(first, last) 就可以把[first, last) 这个范围里面的序列变成下一个全排列。

其中first是指向序列第一个元素的指针(迭代器),last是指向序列最后一个元素后面一个位置的指针(迭代器)。

而且,在当前序列有下一个全排列的时候,函数返回true,否则返回false,完全符合我们的要求啊。

写出来的代码堪比a + b……


Solution

1. 暴力枚举
// UVaOJ 146
// ID Codes
// by A Code Rabbit

#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;

const int LIMITS = 52;

char code[LIMITS];
int len;
bool is_last;

bool Cmp(char ch_a, char ch_b) {
    return ch_a > ch_b;
}

int main() {
    while (gets(code), strcmp(code, "#")) {
        len = strlen(code);
        is_last = true;
        for (int i = len - 2; i >= 0; i--) {
            char* pos = lower_bound(code + i + 1, code + len, code[i], Cmp);
            if (pos != code + i + 1) {
                swap(code[i], *(pos - 1));
                sort(code + i + 1, code + len);
                is_last = false;
                break;
            }
        }
        if (is_last) {
            printf("No Successor\n");
        } else {
            puts(code);
        }
    }

    return 0;
}

2. 利用STL中的 next_permutation( )

// UVaOJ 146
// ID Codes
// by A Code Rabbit

#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;

const int LIMITS = 52;

char code[LIMITS];
int len;
bool is_last;

bool Cmp(char ch_a, char ch_b) {
    return ch_a > ch_b;
}

int main() {
    while (gets(code), strcmp(code, "#")) {
        len = strlen(code);
        if (next_permutation(code, code + len)) {
            puts(code);
        } else {
            printf("No Successor\n");
        }
    }

    return 0;
}








下载PDF

参考资料:无


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值