hdu6351 Beautiful Now 全排列+剪枝(暴力) 2018杭電第五場B題
阿新 • • 發佈:2019-01-03
題意:給你一個不超過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; }