• 2017北京国庆刷题Day1 morning T2


    T2火柴棒 (stick)

    Time Limit:1000ms   Memory Limit:128MB

    题目描述

    众所周知的是,火柴棒可以拼成各种各样的数字。具体可以看下图:

        通过2根火柴棒可以拼出数字“1”,通过5根火柴棒可以拼出数字“2”,以此类推。

        现在LYK拥有k根火柴棒,它想将这k根火柴棒恰好用完,并且想知道能拼出的最小和最大的数分别是多少。

    输入格式(stick.in)

        一个数k。

    输出格式(stick.out)

        两个数,表示最小的数和最大的数。注意这两个数字不能有前导0。

    输入样例

    15

    输出样例

    108 7111111

    数据范围

    对于30%的数据k<=10。

    对于60%的数据k<=20。

    对于100%的数据1<k<=100。

    k<=1e5可做?

    知道什么叫搜索吗?就是dfs啊~

    可以过k<=100000

    贪心有反例 比如31  最小数是20088 不是22888

    加了那么十来句剪枝就很快了~ 理论上还能更快

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    #define N 10100000
    
    using namespace std;
    int n,m,k,len1,len2,num,opt;
    int ans1[N],ans2[N],pre[N],tmp[N],len;
    int use[10]={6,2,5,5,4,5,6,3,7,6};
    
    bool cmp(int a,int b){return a>b;}
    
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    void update(int num)
    {
        if(len1<num) return;//8
        if(len1==num && pre[1]>ans1[1] || pre[2]>ans1[2]) return;//9
        
        for(int i=1;i<=num;i++) tmp[i]=pre[i];
        sort(pre+1,pre+num+1);
        if(pre[1]==0)
        for(int i=1;i<=num;i++)
        {
            if(pre[i]!=0){int j=pre[i];pre[i]=0;pre[1]=j;break;}
        }
        int flag=0;if(len1>num) flag=1;
        else 
        for(int i=1;i<=num;i++)
        {
            if(pre[i]<ans1[i]) 
            {
                flag=1;break;
            }
        }
        if(len1<num) flag=0;
        if(flag) 
        {
            for(int i=1;i<=num;i++) ans1[i]=pre[i];len1=num;
        }
        for(int i=1;i<=num;i++) pre[i]=tmp[i];
    }
    
    void dfs(int res)
    {
        if(res==0)
        {
            update(num);
            return;
        }
        //if(opt) return;
        /*if(res%7==0)
        {
            for(int i=1;i<=num;i++) ans1[i]=pre[i];
            for(int i=num+1;i<=num+res/7;i++) ans1[i]=8;
            opt=1;
        }*/
        if(pre[1]>ans1[1] || pre[2]>ans1[2]) return;//1
        if(len1-num>0 && (len1-num)*7-res<0) return;//2
        if(num>len1/2 && k-res<res) return;//3
        if(num>=len1) return;//4
        if(res<2) return;//5
        
        for(int i=0;i<=9;i++)
        {
        
            if(res==2 && i>1)   break;//6
            if(res==4 && i>4)   break;//7
            if(i==0 && num==0)  continue;
            if(res-use[i]<0)    continue;
            num+=1;
            
            pre[num]=i;
            dfs(res-use[i]);num--;
        }
    }
    
    int main()
    {
        k=read();
        memset(ans1,127/3,sizeof ans1);
        len1=k/7+1;
        if(k%2==0) for(int i=1;i<=k/2;i++) ans2[i]=1;
        if(k%2!=0) {for(int i=2;i<=k/2;i++) ans2[i]=1;ans2[1]=7;}
        if(k%7==0) for(int i=1;i<=k/7;i++) ans1[i]=8,len1=k/7;
        else dfs(k);
        for(int i=1;i<=len1;i++) printf("%d",ans1[i]);
        printf(" ");
        for(int i=1;i<=k/2;i++) printf("%d",ans2[i]);
        return 0;
    }
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    尾递归
    博客搬家 --- CSDN
    sublime text 插件集锦
    chrome 常用插件集锦
    IntelliJ Idea 2017 免费激活方法
    Mac下Java JNI 调C
    webgl学习笔记五-纹理
    webgl学习笔记四-动画
    webgl学习笔记三-平移旋转缩放
    webgl学习笔记二-绘图多点
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7682234.html
Copyright © 2020-2023  润新知