疑似跟题解区的做法不一样,感觉这个会复杂度更高。但是试图剪枝,已经加了一点点剪枝。有没有大佬能想出一些新的剪枝?
顺便这是其他同学的求调链接:这里
#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
*/