HDU 6351 (带技巧的暴力)

Posted shuaihui520

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
",ans,now);
              MAX=max(MAX,ans) , MIN=min(MIN,ans);
            }
        } while(next_permutation(a,a+cnt));
        printf("%d %d
",MIN,MAX);

    }
}
View Code

 

以上是关于HDU 6351 (带技巧的暴力)的主要内容,如果未能解决你的问题,请参考以下文章

hdu6351 Beautiful Now (全排列+循环节)

HDU 6351 Beautiful Now(DFS)多校题解

HDU 6351 Naive Operations(线段树)

hdu 6351Beautiful Now

HDU 2588 GCD Euler + 暴力技巧

关于三分的暴力技巧(暴力好)