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;
}
折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
原文地址:https://www.cnblogs.com/L-Memory/p/7682234.html