TLE 39,dfs求剪枝
查看原帖
TLE 39,dfs求剪枝
941560
HeiCat0725楼主2024/8/17 14:12

疑似跟题解区的做法不一样,感觉这个会复杂度更高。但是试图剪枝,已经加了一点点剪枝。有没有大佬能想出一些新的剪枝?

顺便这是其他同学的求调链接:这里

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
//(在c++98的复古环境中猜测头文件)

int n;
int arr[70],srr[68],p[70],vis[70];
int ok=0;
int sum,ans,res;
bool f;
void dfs(int i,int num){//num是目标木棍数
	if(f) return ;//剪枝
	if(i>n){
		if(ok==num) ans=min(ans,sum/num);//ok是已经拼好的木棍
		f=1;
		return ;
	}
	for(int j=1;j<=num;j++){//枚举放到哪根木棍上
		if(srr[j]+arr[i]>sum/num) continue;
		if(srr[j]+p[i]<sum/num) continue;//剪枝,收效甚微
		if(srr[j]+arr[i]==sum/num) ok++;
		srr[j]+=arr[i];
		dfs(i+1,num);
		if(f) return ;
		srr[j]-=arr[i];
		if(srr[j]+arr[i]==sum/num) ok--;
	}
}
int main(){
	while(cin>>n){
		if(n==0) break;
		sum=0;
		res=1;
		memset(arr,0,sizeof(arr));
		memset(srr,0,sizeof(srr));
		memset(p,0,sizeof(p));
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++){
			scanf("%d",&arr[i]);
			sum+=arr[i];
		}
		for(int i=n;i>=1;i--) p[i]=p[i+1]+arr[i];
		ok=0;
		ans=sum;
		f=0;
		sort(arr+1,arr+n+1,greater<int>());
		while((sum%res!=0)||res<arr[1]) res++;
		for(int i=res;i<=sum/2;i++){//从最小长度开始枚举到和的一半
			if(sum%i!=0) continue;
			memset(srr,0,sizeof(srr));
			dfs(1,sum/i);
			if(ans!=sum) break;
		}
		printf("%d\n",ans);
		break;
	}
	return 0;
}
/*
  5 2 1 5 2 1 5 2 1
  x x x x
  5 5 5 2
  x x x 2
  x x x 2
  1 1 1 c
 */
2024/8/17 14:12
加载中...