来源

2018杭电多校第五场

题意

给你一个正整数 ,你可以把 的第 位数字与第 位数字进行交换,,请注意题目允许自己和自己交换),但是交换过程中不能出现前导零,(例如:11011,第1位和第3位不能交换,因为交换后会出现前导零,输入中保证没有前导零)。现在请你算出经过 次交换后可以得到的最小的整数和最大的整数。

思路

直接利用next_permutation算法进行枚举,复杂度是 ,更新每次的最大值和最小值,由于,这个计算量还是很大,要通过交换的次数是否超过 剪枝,又通过直接判定 再剪枝。

WA点

杭电C++会T,G++就能过,什么神仙编译器。。。。
特别注意前导0的存在。
数组尽量开小点,bool int也可以稍微加速。

另一种思路

对于每一位,搜索后面的数的最大值/最小值是否有大于/小于自己的,有就交换,这样理论复杂度只有 ,但是总代码量其实差不多。

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;

const int maxn = 10;
bool vis[maxn];
int bit[maxn], id[maxn];
char s[maxn];

int k, len;

inline bool check() {
    memset(vis,0,sizeof(vis));
    int cnt=0;
    for(int i=0;i<len;i++) {
        if(!vis[i]) {
            int t=-1;
            while(!vis[i]) {
                t++;
                vis[i]=1;
                i=id[i];
            }
            cnt+=t;
            if(cnt>k) return false;
        }
    }
    return true;
}

int cmp(int a, int b) {
    return a>b;
}

int main() {
    int t; scanf("%d",&t);
    while(t--) {
        scanf("%s",s);
        scanf("%d",&k);
        len=strlen(s);
        for(int i=0;i<len;i++) {
            bit[i]=s[i]-'0';
            id[i]=i;
        }

        if(k>=len) {
            sort(bit,bit+len);
            int pos=0; while(bit[pos]==0) pos++;
            if(bit[0]==0) swap(bit[0],bit[pos]);
            for(int i=0;i<len;i++) printf("%d",bit[i]); printf(" "); 
            sort(bit,bit+len,cmp);
            for(int i=0;i<len;i++) printf("%d",bit[i]); printf("\n");
            continue;
        }

        int mi=2e9, mx=-1;
        do {
            if(bit[id[0]] && check()) {
                int temp=0;
                for(int i=0;i<len;i++) {
                    temp=temp*10+bit[id[i]];
                }
                mi=min(mi,temp);
                mx=max(mx,temp);
            }
        } while(next_permutation(id,id+len));
        printf("%d %d\n",mi,mx);
    }
}