Beautiful Now(爆搜dfs)

Beautiful Now

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


 

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

 

 

Recommend

chendu   |   We have carefully selected several similar problems for you:  6361 6360 6359 6358 6357 

题意:给一个数字n,可以各个位之间交换,再进行最多k次交换后,能构成的最小和最大的数是多少。

分析:拿贪心搞的话策略总是不完备,数据量给的刚好,所以就爆搜吧,需要一些剪枝,不然也是TLE。

1、首先对于k大于等数字n的长度-1就一定可以把所有位都换一遍,那么最大结果一定是这些数字排列后所构成的最大结果,最小结果也是这些数字排列后形成的最小结果。

2、对于k比较小的情况直接dfs,以找最小数字为例,每次都去找剩余位上最小的数字是多少,找到了就用当前位和它交换位置,进入下一个状态。

3、具体过程看注释吧。

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<math.h>
#include<queue>
#include<deque>
#include<ctype.h>
#include<map>
#include<set>
#include<stack>
#include<string>
#define INF 100
#define FAST_IO ios::sync_with_stdio(false)
const double PI = acos(-1.0);
const double eps = 1e-6;
const int MAX=1e5+10;
const int mod=1e9+7;
typedef long long ll;
using namespace std;
#define gcd(a,b) __gcd(a,b)
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
inline ll qpow(ll a,ll b){ll r=1,t=a; while(b){if(b&1)r=(r*t)%mod;b>>=1;t=(t*t)%mod;}return r;}
inline ll inv1(ll b){return qpow(b,mod-2);}
inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll r=exgcd(b,a%b,y,x);y-=(a/b)*x;return r;}
inline ll read(){ll x=0,f=1;char c=getchar();for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;for(;isdigit(c);c=getchar()) x=x*10+c-'0';return x*f;}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
ll n,k;
string s;
string mins,maxs;
string tmins,tmaxs;
int cmp(char x,char y)
{
    return x>y;
}

void dfs1(ll indx,ll cut,string x)//最小的情况
{
    if(indx==s.length()-1 || cut>k-1)
    {
        tmins=min(tmins,x);
        return ;
    }

    if(x[indx]==mins[indx])//当前数字已经在最优位置上,不用再交换了。
    {
        dfs1(indx+1,cut,x);
        return;
    }

    char p=INF;
    for(ll i=indx+1;i<x.length();i++)
    {
        if(indx==0 && x[i]=='0')
            continue;
        p=min(p,x[i]);
    }

    if(p==INF)
    {
        dfs1(indx+1,cut,x);
        return ;
    }

    for(ll i=indx+1;i<x.length();i++)
    {
        if(x[i]==p)
        {
            swap(x[indx],x[i]);
            dfs1(indx+1,cut+1,x);
            swap(x[indx],x[i]);
        }
    }
}

void dfs2(ll indx,ll cut,string x)//最大的情况
{
    if(indx==s.length()-1 || cut>k-1)
    {
        tmaxs=max(tmaxs,x);
        return ;
    }

    if(x[indx]==maxs[indx])//
    {
        dfs2(indx+1,cut,x);
        return ;
    }

    char p=-1;
    for(ll i=indx+1;i<x.length();i++)
        p=max(p,x[i]);

    for(ll i=indx+1;i<x.length();i++)
    {
        if(x[i]==p)
        {
            swap(x[indx],x[i]);
            dfs2(indx+1,cut+1,x);
            swap(x[indx],x[i]);
        }
    }
}
void solve()
{
    tmins=tmaxs=s;
    dfs1(0,0,s);
    dfs2(0,0,s);
}
void init()
{
    cin>>n>>k;
    s.clear();

    while(n)
    {
        s=s+(char)(n%10+'0');
        n=n/10;
    }
    reverse(s.begin(),s.end());//反转。
    mins=s;
    maxs=s;
    sort(mins.begin(),mins.end());
    sort(maxs.begin(),maxs.end(),cmp);
    if(mins[0]=='0')//最小情况时开头为0用次小的换掉这个0。
    {
        int indx=0;
        while(mins[indx]=='0')
            indx++;
        swap(mins[0],mins[indx]);
    }
}
int main()
{

    ll T;
    cin>>T;
    while(T--)
    {
        init();
        if(k>=s.length()-1)//特判 k大于n的长度一定可以构成最小和最大的这种情况。
            cout<<mins<<' '<<maxs<<endl;
        else
        {
            solve();
            cout<<tmins<<' ';
            cout<<tmaxs<<endl;
        }
    }

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值