HDU-6351-杭电多校第五场-Beautiful Now

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/monochrome00/article/details/81462068

题目链接<http://acm.hdu.edu.cn/showproblem.php?pid=6351>


题意:

给你一个数,最多可以进行k次的操作,每次操作可以把某一位数字和另一位数字交换,可以与自己交换(就相当于不交换),问k次操作后能获得的最大值和最小值是多少。


题解:

一开始应该都会考虑贪心,从高位开始,一步步把数值较大的提上来。比如123,把3提上来转化成321。

这就会产生一个问题,如果后面有多位相同的,应该换哪个?比如1233,只换一次,那应该是换最后一个也就变成了3231。把最靠后的最大值换上来应该是最优的。

可是这并不对。比如6299。交换一次变成9296,交换两次变成9926,交换三次变成9962。

可其实也可以这样交换,6299->9269->9962。只需要两次交换就成了最大值。

所以贪心是错的。

但我们也可以发现,唯一能产生错误的原因就是因为后面所找到的最大值有多个的情况,我们就只需把后面的每种情况搜索一遍就行了。

另外可以得出一个结论,任意的m位数,转换成另一个数,所需要的转换次数不超过m-1次.。所以可以直接进行k=min(k,位数)。

我是通过数字实现的,如果用字符串的话会更方便,也会更快。

#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long ll;
const ll N=1e5+7;
const ll inf=1e5+7;
ll n,k,dn;
ll a[50];
struct Node{
    ll x,i,stp;
    Node(ll x,ll i,ll stp):x(x),i(i),stp(stp){}
};
ll bfs1(){
    queue<Node>q;
    q.push(Node(n,dn,0));
    ll ans=(ll)1e10;
    while(!q.empty()){
        Node t=q.front();q.pop();
        ans=min(ans,t.x);
        if(t.stp==k) continue;
        if(t.i==1) continue;
        ll tmp=t.x,cnt=0;
        while(tmp){
            a[++cnt]=tmp%10;
            tmp/=10;
        }
        ll mi=t.i;
        for(ll i=t.i-1;i>=1;i--){
            if(a[i]==a[t.i]) continue;
            if(a[i]==0&&t.i==dn) continue;
            if(a[i]<a[mi]) mi=i;
        }
        if(mi==t.i)
            q.push(Node(t.x,t.i-1,t.stp));
        else{
            for(ll i=t.i-1;i>=1;i--){
                if(a[i]==a[mi]){
                    swap(a[i],a[t.i]);
                    ll tmp=0;
                    for(ll j=cnt;j>=1;j--)
                        tmp=tmp*10+a[j];
                    q.push(Node(tmp,t.i-1,t.stp+1));
                    swap(a[i],a[t.i]);
                }
            }
        }
    }
    return ans;
}
ll bfs2(){
    queue<Node>q;
    q.push(Node(n,dn,0));
    ll ans=0;
    while(!q.empty()){
        Node t=q.front();q.pop();
        ans=max(ans,t.x);
        if(t.stp==k) continue;
        if(t.i==1) continue;
        ll tmp=t.x,cnt=0;
        while(tmp){
            a[++cnt]=tmp%10;
            tmp/=10;
        }
        ll ma=t.i;
        for(ll i=t.i-1;i>=1;i--){
            if(a[i]==a[t.i]) continue;
            if(a[i]>a[ma]) ma=i;
        }
        if(ma==t.i)
            q.push(Node(t.x,t.i-1,t.stp));
        else{
            for(ll i=t.i-1;i>=1;i--){
                if(a[i]==a[ma]){
                    swap(a[i],a[t.i]);
                    ll tmp=0;
                    for(ll j=cnt;j>=1;j--)
                        tmp=tmp*10+a[j];
                    q.push(Node(tmp,t.i-1,t.stp+1));
                    swap(a[i],a[t.i]);
                }
            }
        }
    }
    return ans;
}
int main()
{
    ll t;
    scanf("%lld",&t);
    while(t--){
        scanf("%lld%lld",&n,&k);
        ll tt=n;
        dn=0;
        while(tt){
            dn++;
            tt/=10;
        }
        k=min(k,dn-1);
        ll ans1=bfs1();
        ll ans2=bfs2();
        printf("%lld %lld\n",ans1,ans2);
    }
}

猜你喜欢

转载自blog.csdn.net/monochrome00/article/details/81462068