1. 程式人生 > >hdu Beautiful Now

hdu Beautiful Now

                                     Beautiful Now

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2386    Accepted Submission(s): 866



 

Problem Description

Anton has a positive integer n, however, it quite looks like a mess, so he wants to make it beautiful after k swaps of digits.
Let the decimal representation of n as (x1x2⋯xm)10 satisfying that 1≤x1≤9, 0≤xi≤9 (2≤i≤m), which means n=∑mi=1xi10m−i. In each swap, Anton can select two digits xi and xj (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 k swaps?

 

 

Input

The first line contains one integer T, indicating the number of test cases.
Each of the following T lines describes a test case and contains two space-separated integers n and k.
1≤T≤100, 1≤n,k≤109.

 

 

Output

For each test case, print in one line the minimum integer and the maximum integer which are separated by one space.

 

 

Sample Input

 

5 12 1 213 2 998244353 1 998244353 2 998244353 3

 

 

Sample Output

 

12 21 123 321 298944353 998544323 238944359 998544332 233944859 998544332

 

 

Source

2018 Multi-University Training Contest 5

看了好多部落格,發現有用搜索的,有用全排列的,在這裡全排列是可以暴力過的

最大的難度是次數怎樣去實現,用下標來實現,當訪問過的就標記為1,沒訪問過的標記為0,顯然訪問過的不能再進行下去,跳出迴圈,這樣去卡它的次數

用全排列的好處是,它會自動排好序,例如

#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
    int n;
    while(scanf("%d",&n)&&n){
        int a[1000];
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        sort(a,a+n);//可以自行測試一下刪除後的結果
        do{
            for(int i=0;i<n;i++)
                printf("%d ",a[i]);
            printf("\n");
        }while(next_permutation(a,a+n));
    }
    return 0;
}

3
7 5 3
3 5 7
3 7 5
5 3 7
5 7 3
7 3 5
7 5 3

只需判斷出符合次數條件,且在此基礎上還是最大的,最小的即可

全排列下標,因為字元可以重複,若不用此方法,計算次數的時候可能會WA

#include<bits/stdc++.h>
using namespace std;
int vis[20];
int xb[20];//下標
int k,len;
char s[20];//字元陣列

int cheak()//檢查交換次數
{
    fill(vis,vis+len,0);每個字元長度不一樣,所以用fill會將不同長度的字元陣列置為0
    int p=0;
    for(int i=0;i<len;i++)
    {
        if(vis[i])  continue;
        int ans=0;
        while(vis[i]==0)
        {
            ans++;
            vis[i]=1;
            i=xb[i];
        }
         p=p+ans-1;
         if(p>k)  return 0;//可能在小於k的時間就已經找到最小和最大值
     }
     return 1;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s %d",s,&k);
        len=strlen(s);
        for(int i=0;i<len;i++)
        {
            xb[i]=i;//下標初始化
        }
        int max1=0;
        int min1=1e9+5;
        do
        {

          if(s[xb[0]]!='0'&&cheak())
          {
              int sum=0;
              for(int i=0;i<len;i++)
              {
                  sum=sum*10+s[xb[i]]-'0';
              }
              if(sum<min1)
              {
                  min1=sum;
              }
              if(sum>max1)
              {
                  max1=sum;
              }
          }
        }while(next_permutation(xb,xb+len));//全排列
        printf("%d %d\n",min1,max1);
    }
    return 0;

}

怎樣去查詢它的次數 

          i       0 1 2 3
陣列a[i]          1 4 7 5
下標b[i]          0 1 2 3

          i       0 1 2 3
交換一次 下標b[i] 0 1 3 2
             a[i] 1 4 5 7
可以發現如果下標2,3改變,則去看當i=2的時候,下標對應的是b[2]=3,
將b[2]的值作為下標去檢查,此時當i=3時看是否b[3]與原序列改變
這個規律之前我也沒發現,真的很神奇。。。。