1. 程式人生 > >hdu6351 Beautiful Now 全排列+剪枝(暴力) 2018杭電第五場B題

hdu6351 Beautiful Now 全排列+剪枝(暴力) 2018杭電第五場B題

題意:給你一個不超過10^9的數n,和一個k;

有一種操作方式交換這個數的某一位與另一位進行交換 比如 201 可以換成 102,讓你進行k次操作,求出交換後最大的數字和最小的數字.

要點:1 . 某一位的數字可以和它本身進行交換

           2 .交換的數字不可以有前導零(即第一位不可以是0)

題解:如果這個數字是n位數,那麼其交換不超過n-1次就可以變成最大值和最小值,可以根據這個點進行剪枝,題目給的數字不超過10^9,那麼進行全排列直接暴力就好了,時間複雜度最多10!,這道題給的時間限制為2500ms,跑一次暴力大概2000多ms,弱雞的我不會貪心。

題目地址

#include<bits/stdc++.h>
using namespace std;

int maxx, minn, k, len;
int c[20], sum1[20], sum2[20], p[20];
char ss[20];

void update() {
    if(c[p[1]] == 0){
        return;
    }
    for(int i = 1; i <= len; i++){
        sum1[i] = p[i];
    }
    int kk = 0, s = 0;
    for(int i = 1; i <= len; i++){
        s = s * 10 + c[p[i]];
        if(sum1[i] != i){
            for(int j = i+1; j <= len; j++){
                if(sum1[j] == i){
                    swap(sum1[i], sum1[j]);
                    kk++;
                    if(kk > k) return;
                    break;
                }
            }
        }
    }
    if(kk > k){
        return ;
    }
    maxx = max(maxx, s);
    minn = min(minn, s);
}

int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        memset(sum1,0,sizeof(sum1));
        memset(sum2,0,sizeof(sum2));
        scanf("%s%d",ss,&k);
        len = strlen(ss);
        for(int i = 0; i < len; i++) {
            c[i+1] = ss[i] - '0';
            sum1[c[i+1]]++;
            sum2[c[i+1]]++;
        }
        if(k >= len-1) {//剪枝 
            for(int i = 1; i <= 9; i++) {
                if(sum1[i]) {
                    printf("%d",i);
                    sum1[i]--;
                    break;
                }
            }
            for(int i = 0; i <= 9; i++) {
                while(sum1[i]) {
                    printf("%d",i);
                    sum1[i]--;
                }
            }
            printf(" ");
            for(int i = 9; i >= 0; i--) {
                while(sum2[i]) {
                    printf("%d",i);
                    sum2[i]--;
                }
            }
            printf("\n");
            continue;
        }
        for(int i = 1; i <= len; i++){
            p[i] = i;
        }
        minn = 2e9, maxx = -1;
        do{
            update();
        }while(next_permutation(p+1,p+len+1));//全排列 
        printf("%d %d\n",minn, maxx);
    }
    return 0;
}