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; }
折花枝,恨花枝,准拟花开人共卮,开时人去时。
怕相思,已相思,轮到相思没处辞,眉间露一丝。