rt,从POJ来的,一直TLE,求神犇帮忙。
#include<bits/stdc++.h>
using namespace std;
#define in_bufsize 1<<2
#define out_bufsize 1<<2
#define flush() fwrite(buffer,1,pppp+1,stdout),pppp=-1
#define getc() getchar()//p1==p2&&(p2=(p1=buf)+fread(buf,1,in_bufsize,stdin),p1==p2)?EOF:*p1++
#define putc(c) putchar(c) //pppp==out_bufsize?flush(),buffer[++pppp]=c:buffer[++pppp]=c
#define rull reg unsigned long long
#define ull unsigned long long
#define lli long long
#define reg register
#define pow2(x) (1<<(x))
#define lb(x) (x&-x)
#define clamp(v,max,min) ((v)>(max)?(max):(v)<(min)?(min):(v))
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)<0?(-(x)):(x))
#define FileRW freopen("in.txt","r",stdin),freopen("out.txt","w",stdout)
static char buf[in_bufsize],*p1(buf),*p2(buf),buffer[out_bufsize];
static int pppp=-1;
inline int read(){
reg int a=0;
reg bool isF=0;
reg char c=getc();
while(c<'0'||c>'9'){
isF=(c=='-');
c=getc();
}
while(c>='0'&&c<='9'){
a=(a<<3)+(a<<1)+(c^48);
c=getc();
}
return isF?-a:a;
}
#define swrite(s) for(reg unsigned int i=0;s[i]!='\0';++i){putc(s[i]);}
inline void write(reg int a){
if(a==INT_MIN){
swrite("-2147483648");
return;
}
if(a<0){
a=-a;
putc('-');
}
reg short top=0;
static char sc[15];
do{
sc[top++]=a%10+48;
a/=10;
}while(a);
while(top){
putc(sc[--top]);
}
}
inline int gcd(reg int x,reg int y){
while(y^=x^=y^=x%=y);
return x;
}
int n,a[70],bianlen,bianshu,nexta[70];
int maxlen=-2147483647,lenhe=0;
bool vd[70],over;
inline bool cmp(int &a,int val){
return val<a;
}
void dfs(reg int bian,reg int changhe,reg int starti){//bian:第?条边 changhe:这条边已经拼的长度 starti从第?条边开始
if(over){
return;
}
if(bian==bianshu){
write(bianlen);
putc('\n');
over=1;
return;
}
starti=lower_bound(a+starti,a+n,bianlen-changhe,cmp)-a;//找到木棍长度不大于未拼长度的第一个木棍
for(reg int i=starti;i<n;i++){
if(vd[i]){
continue;
}
if(changhe+a[i]<=bianlen){
vd[i]=1;
if(changhe+a[i]==bianlen){
dfs(bian+1,0,0);//进入下一条边
}else{
dfs(bian,changhe+a[i],i+1);
}
vd[i]=0;
if(changhe==0||changhe+a[i]==bianlen){//发现又回来了,没搭成功,且changhe==0||changhe+a[i]==bianlen时,说明前面拼错了,返回上一层
return;
}
}
i=nexta[a[i]];//跳
}
}
int main(){
while(n=read()){
maxlen=-2147483647;
lenhe=0;
over=0;
memset(vd,0,sizeof(vd));
for(reg int i=0;i<n;i++){
a[i]=read();
maxlen=max(maxlen,a[i]);//最大长度
lenhe+=a[i];
}
sort(a,a+n,greater<int>());//1:从小到大排序
for(reg int i=0;i<n;i++){
if(a[i]!=a[i+1]){
nexta[a[i]]=i;//2:nexta[i]=最后一个等于i的元素的下标
}
}
for(reg int i=maxlen,maxi=lenhe>>1;/*最大到长度和的一半*/i<=maxi;i++){
if(lenhe%i==0){
bianlen=i;//预计每条边的长度
bianshu=lenhe/i;//边的数量
dfs(1,0,0);
if(over){
break;
}
}
}
if(over){
continue;
}
write(lenhe);
putc('\n');
}
flush();
return 0;
}