死活TLE求助(有注释)
查看原帖
死活TLE求助(有注释)
528289
apphhzp楼主2023/1/1 00:22

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;
}
2023/1/1 00:22
加载中...