HDU 6351 (带技巧的暴力)

题意:给定一个数,和一个最多交换次数k,问在不超过k次操作的情况,问可以得到的最大值和最小值是多少?

 

个人解题的艰辛路程 , 开始是想到了暴力枚举的可能 , 打出来发现在判断枚举的数组与原来数组交换了多少次出现了错误 , 我们扫一遍枚举的数组于原来的数组不相同就往后面找到相同 , 但这个是不行的 , 这样必须是每一位数都不一样才可以 , 然后无耻的看了题解 , O!原来是枚举位置 ,  然后题解,超时了 , 想了想发现当k>cnt 的时候 ,是一定可以构成出来的 ,不需要枚举 , 所以加了这样Ala 

 

#include<bits/stdc++.h>
using namespace std ;
int A[20],a[20],T[20],sumMAX[20],sumMIN[20];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(sumMIN,0,sizeof(sumMIN));
        memset(sumMAX,0,sizeof(sumMAX));
        int x,k;
        scanf("%d%d",&x,&k);
        int cnt=0;
        while(x)
        {

            a[cnt++]=x%10;
            sumMAX[x%10]++;sumMIN[x%10]++;
            x/=10;
        }
        for(int i=cnt-1 ; i>=0 ; i--)
        {
            A[cnt-1-i]=a[i];
        }
        for(int i=0 ; i<cnt ; i++) a[i]=i;
        int MIN=0x3f3f3f3f,MAX=-1;
        if(k>=cnt-1)///剪枝
        {
            for(int i=1 ; i<=9 ; i++)///第一位排除0
            {
                if(sumMIN[i])
                {
                    printf("%d",i);
                    sumMIN[i]--;
                    break;
                }
            }
            for(int i=0 ; i<=9 ; i++)
            {
                while(sumMIN[i])
                {
                    printf("%d",i);
                    sumMIN[i]--;
                }
            }
            printf(" ");
            for(int i=9 ; i>=0 ; i--)
            {
                while(sumMAX[i])
                {
                    printf("%d",i);sumMAX[i]--;
                }
            }
            puts("");continue;
        }
        do
        {
            int now=0;
            int ans=0;
            if(A[a[0]]==0) continue;
            for(int i=0 ; i<cnt ; i++)
            T[i]=a[i];
            for(int i=0 ; i<cnt ; i++)
            {
                if(T[i]!=i)
                {
                    now++;
                    if(now>k) break;
                    for(int j=i+1 ; j<cnt ; j++)
                    {
                        if(T[j]==i)
                        {
                            swap(T[i],T[j]);break;
                        }
                    }
                }
                if(now>k) break;
                ans=ans*10+A[a[i]];

            }
            if(now<=k)
            {
            //  printf("%d %d\n",ans,now);
              MAX=max(MAX,ans) , MIN=min(MIN,ans);
            }
        } while(next_permutation(a,a+cnt));
        printf("%d %d\n",MIN,MAX);

    }
}
View Code

 

转载于:https://www.cnblogs.com/shuaihui520/p/10336483.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值