题目描述(洛谷1120)乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50,
现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。
给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
1.显然枚举所有情况再用递归判断是否可行很浪费时间,再输入数据时统计sum,当g,k都为整数时在调用递归判断是否可行;
void work(int k,int n,int c){
if(c==g) flag=1;
if(!n) {work(k,k,c+1);return;}
for(int i=50;i>0&&!flag;--i){
if(lenth[i]&&i<=n) {
--lenth[i];
work(k,n-i,c);
++lenth[i];
if(n==k||n==i) return;
}
}
}
然而还是会超时的,洛谷数据更新了!!!!
我一直超时服了,看了dalao的代码,!!!少了一些小优化
void work(int k,int n,int c,int q){
if(c==g) flag=1;
if(!n) {work(k,k,c+1,maxa);return;}
for(int i=q;i>=mina&&!flag;--i){
if(lenth[i]&&i<=n) {
--lenth[i];
work(k,n-i,c,i);
++lenth[i];
if(n==k||n==i) return;
}
}
}
对特殊数据有很大的优化效果
不使用flag,在得到结果时还要在层层返回,浪费时间,直接打印k,exit(0);否则在最后就回到了主函数直接输出sum。
其实还可以手写输入代码。
#include<bits/stdc++.h>
using namespace std;
int N,sum,maxa,g,mina=69;
int tiao[55];
void read(){
scanf("%d",&N);
for(int i=1,j=0;i<=N;++i){
int x;scanf("%d",&x);
if(x>50)continue;
sum+=x;
if(x>maxa) maxa=x;
if(x<mina)mina=x;
tiao[x]++;
}
}
void work(int k,int n,int c,int q){
if(c==g) {printf("%d",k);exit(0);};
if(!n) {work(k,k,c+1,maxa);return;}
for(int i=q;i>=mina;--i)
if(tiao[i]&&i<=n) {
--tiao[i]; work(k,n-i,c,i);++tiao[i];
if(n==k||n==i) return ;
}
}
int main(){
read();
N=sum>>1;
for(int i=maxa;i<=N;++i){
if(sum%i==0){
g=sum/i;
work(i,i,0,maxa);
}
}
printf("%d",sum);
return 0;
}