zoukankan      html  css  js  c++  java
  • 2018杭电多校第五场1002(暴力DFS【数位】,剪枝)

    //never use translation
    #include<bits/stdc++.h>
    using namespace std;
    int k;
    char a[20];//储存每个数的数值
    int times[20];//mn次数
    int timess[20];//mx次数
    int len;
    int mn;
    int mx;
    int kk,sum;
    void solve()
    {
        kk=0,sum=0;
        if(a[times[1]]==0)
            return;
        for(int i=1;i<=len;i++)
            timess[i]=times[i];//储存现在的数位情况,times因排序而发生递增
        for(int i=1;i<=len;i++)
        {
            sum=sum*10+a[times[i]];//记录按照数位变化而产生的数值
            if(timess[i]!=i)//该位置发生变动
            {
                for(int j=i+1;j<=len;j++)
                {
                    if(timess[j]==i)//找到和前面发生变动的数字exchange的数位
                    {
                        swap(timess[i],timess[j]);//交换以免在后续的查找中将交换的数位查找两次
                        kk++;//查找次数++
                        if(kk>k)
                            return;
                        break;//寻找下一个发生变动的数位
                    }
                }
            }
        }
        if(kk>k)
            return;
        mx=max(mx,sum);
        mn=min(mn,sum);
        return;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%s%d",a+1,&k);
            len=strlen(a+1);
        if(len==10)
                printf("1000000000 1000000000 ");//剪枝
        else
        {
            memset(times,0,sizeof(times));
            memset(timess,0,sizeof(timess));
            for(int i=1;i<=len;i++)
            {
                a[i]-='0';
                times[a[i]]++;
                timess[a[i]]++;//计数
            }
            if(k>=len-1)//剪枝
            {
                for(int i=1;i<=9;i++)//第一位非零
                {
                    if(times[i])
                    {
                        printf("%d",i);
                        times[i]--;
                        break;
                    }
                }
                for(int i=0;i<=9;i++)
                {
                    while(times[i])//将所有数全部贪心输出
                    {
                        printf("%d",i);
                        times[i]--;
                    }
                }
                printf(" ");
                for(int i=9;i>=1;i--)//和上面反着来
                {
                    if(timess[i])
                    {
                        printf("%d",i);
                        timess[i]--;
                        break;
                    }
                }
                for(int i=9;i>=0;i--)
                {
                    while(timess[i])
                    {
                        printf("%d",i);
                        timess[i]--;
                    }
                }
                printf(" ");
            }
            else//还有一种利用暴力dfs的方法是最初的想法,听完讲解后觉得按照数位全排列技巧性高一点
            {
                mx=0,mn=1e10;//反向设定最值
                for(int i=1;i<=len;i++)
                {
                    times[i]=i;//记录原始数位
                }
                do
                {
                    solve();
                }while(next_permutation(times+1,times+1+len));//至少进行一次更新最值
                //全排列函数按照字典序寻找下一种情况,这里按照数位从最小的1~n开始枚举到n~1
                //prev_permutation按照字典序寻找上一种情况
                printf("%d %d ",mn,mx);
            }
        }
        }
        return 0;
    }

    //遇见数字较大然而问题和单独的数有关时联想可否用数位思想解决,数位和数之间建立联系,数位处理问题时较为简单便利

    保持热爱 不懈努力 不试试看怎么知道会失败呢(划掉) 世上无难事 只要肯放弃(划掉)
  • 相关阅读:
    前端事件系统(四)
    前端事件系统(三)
    前端事件系统(二)
    前端事件系统(一)
    前端图片选择问题
    浅谈前端移动端页面开发(布局篇)
    诙谐论设计模式(一)——创建型设计模式
    总结三年未满的工作经历,写下自己对技术的坚持
    java内存优化牛刀小试
    将上下文融入知识图谱以进行常识推理
  • 原文地址:https://www.cnblogs.com/ldudxy/p/9435490.html
Copyright © 2011-2022 走看看