天天看點

C - Beautiful Now

Anton has a positive integer 

nn, however, it quite looks like a mess, so he wants to make it beautiful after kk swaps of digits. 

Let the decimal representation of nn as (x1x2⋯xm)10(x1x2⋯xm)10 satisfying that 1≤x1≤91≤x1≤9, 0≤xi≤90≤xi≤9 (2≤i≤m)(2≤i≤m), which means n=∑mi=1xi10m−in=∑i=1mxi10m−i. In each swap, Anton can select two digits xixi and xjxj (1≤i≤j≤m)(1≤i≤j≤m) and then swap them if the integer after this swap has no leading zero. 

Could you please tell him the minimum integer and the maximum integer he can obtain after kk swaps?

5
12 1
213 2
998244353 1
998244353 2
998244353 3      
12 21
123 321
298944353 998544323
238944359 998544332
233944859 998544332

      
1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 
  6 using namespace std;
  7 
  8 int maxx,minn,k,len;
  9 int c[20],sum1[20],sum2[20],p[20];
 10 char ss[20];
 11 
 12 void update()
 13 {
 14     if(c[ p[1] ]==0)
 15     {
 16         return;
 17     }
 18     // 用sum1記錄目前排列
 19     for(int i=1;i<=len;++i)
 20     {
 21         sum1[i]=p[i];
 22     }
 23 
 24     int kk=0,s=0;
 25     for(int i=1;i<=len;++i)
 26     {
 27         s=s*10 + c[ p[i] ];
 28         if(sum1[i] != i)
 29         {
 30             for(int j=i+1;j<=len;++j)
 31             {
 32                 if(sum1[j]==i)
 33                 {
 34                     swap(sum1[i],sum1[j]);
 35                     ++ kk;
 36                     // 這一序列不能在k步内實作
 37                     if(kk>k)
 38                     {
 39                         return;
 40                     }
 41                     break;
 42                 }
 43             }
 44         }
 45     }
 46 
 47     // 目前隊列滿足條件
 48     // 更新最大最小值
 49     maxx=max(maxx,s);
 50     minn=min(minn,s);
 51 }
 52 
 53 int main()
 54 {
 55     int T;
 56     scanf("%d",&T);
 57     while(T--)
 58     {
 59         memset(sum1,0,sizeof(sum1));
 60         memset(sum2,0,sizeof(sum2));
 61         scanf("%s %d",ss,&k);
 62 
 63         len=strlen(ss);
 64 
 65         for(int i=0;i<len;++i)
 66         {
 67             // 字元轉數字
 68             c[i+1]=ss[i]-'0';
 69             ++ sum1[ c[i+1] ];
 70             ++ sum2[ c[i+1] ];
 71         }
 72 
 73         // 剪枝
 74         if(k>=len-1)
 75         {
 76             // 輸出最小數
 77             // 輸出第一位(特判非零)
 78             for(int i=1;i<=9;++i)
 79             {
 80                 if(sum1[i])
 81                 {
 82                     printf("%d",i);
 83                     -- sum1[i];
 84                     break;
 85                 }
 86             }
 87 
 88             for(int i=0;i<=9;++i)
 89             {
 90                 while(sum1[i])
 91                 {
 92                     printf("%d",i);
 93                     --sum1[i];
 94                 }
 95             }
 96 
 97             printf(" ");
 98 
 99             // 輸出最大數
100             for(int i=9;i>=0;--i)
101             {
102                 while(sum2[i])
103                 {
104                     printf("%d",i);
105                     -- sum2[i];
106                 }
107             }
108             printf("\n");
109             continue;
110         }
111 
112         // 未能剪枝
113 
114         // 找一個互不相等的排列(從小到大有序)
115         // 以初始排列為目前數字的編号
116         for(int i=1;i<=len;++i)
117         {
118             p[i]=i;
119         }
120         // 初始化最大最小值
121         minn=2e9;
122         maxx=-1;
123         // 自目前排列開始更新滿足條件時的最大最小值
124         do
125         {
126             update();
127         }while(next_permutation(p+1,p+len+1));  // 需要頭檔案algor
128         // 九位數的全排列,有362880種
129         // 最多嘗試次數,為九次
130         // 複雜度約為 10^7
131         printf("%d %d\n",minn,maxx);
132     }
133     return 0;
134 }