首先for一遍看拼成多长的木棍
然后DFS
以前你已经拼好了sum根棍子
这根棍子你已经拼了len长度
从1到50枚一遍,看放多长的木棍,然后接着搜
恩下面给出裸搜代码,30分到手
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#define MAX 50
#define rg register
using namespace std;
int n,N[MAX+1],Nlen,yes,Max=0,Sum=0;
void dfs(int sum,int len){
//已经凑好了sum根,最后一根长度len
if(len==Nlen)sum++,len=0;
if(sum==Sum/Nlen){yes=1;return;}
for(rg int i=Nlen-len;i;i--)
if(N[i]){
N[i]--;
dfs(sum,len+i);
N[i]++;
}
}
int main(){
rg int data;
scanf("%d",&n);
for(rg int i=1;i<=n;i++){
scanf("%d",&data);
if(data>MAX)--i,--n;
else Max=max(Max,data),Sum+=data,N[data]++;
}
for(rg int i=Max;i<=Sum;i++)
if(!(Sum%i)){
Nlen=i;
dfs(0,0);
if(yes){printf("%d\n",i);break;}
}
return 0;
}
/*
9
5 2 1 5 2 1 5 2 1
*/
显然30分无法让利欲熏心的你满足
于是我开始想怎么剪枝
题目所给的木棍称作小木棍,要拼接的木棍成为大木棍
有一个傻逼剪枝:如果dfs之后yes=1了,直接跳出循环
然后,对于每根大木棍,可以将拼接的小木棍sort一遍,所以可以从大到小放棍子(自己想为什么不能从小到大)
给出剪枝后的代码,加上这两个剪枝以后有80分了
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#define MAX 50
#define rg register
using namespace std;
int n,N[MAX+1],Nlen,yes,Max=0,Sum=0;
void dfs(int sum,int len,int last){
//已经凑好了sum根,最后一根长度len,前一个放last
if(len==Nlen)sum++,len=0,last=MAX;
if(sum==Sum/Nlen){yes=1;return;}
for(rg int i=min(last,Nlen-len);i;i--)
if(N[i]){
N[i]--;
dfs(sum,len+i,i);
if(yes)return;
N[i]++;
}
}
int main(){
rg int data;
scanf("%d",&n);
for(rg int i=1;i<=n;i++){
scanf("%d",&data);
if(data>MAX)--i,--n;
else Max=max(Max,data),Sum+=data,N[data]++;
}
for(rg int i=Max;i<=Sum;i++)
if(!(Sum%i)){
Nlen=i;
dfs(0,0,MAX);
if(yes){printf("%d\n",i);break;}
}
return 0;
}
/*
9
5 2 1 5 2 1 5 2 1
*/
那么如何AC?
如果一根大木棍的len==0,且dfs完第一遍之后没有答案,那么之后的dfs肯定没有答案,这很科学
加上愉快AC
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#define MAX 50
#define rg register
using namespace std;
int n,N[MAX+1],Nlen,rest,yes,Max=0,Sum=0;
void dfs(int sum,int len,int last){
//已经凑好了sum根,最后一根长度len,前一个放last
if(len==Nlen)sum++,len=0,last=MAX;
if(rest==1){yes=1;return;}
for(rg int i=min(last,Nlen-len);i;i--)
if(N[i]){
N[i]--,rest--;
dfs(sum,len+i,i);
if(yes)return;
N[i]++,rest++;
if(!len)return;
}
}
int main(){
rg int data;
scanf("%d",&n);
for(rg int i=1;i<=n;i++){
scanf("%d",&data);
if(data>MAX)--i,--n;
else Max=max(Max,data),Sum+=data,N[data]++;
}
for(rg int i=Max;i<=Sum;i++)
if(!(Sum%i)){
Nlen=i,rest=n;
dfs(0,0,MAX);
if(yes){printf("%d\n",i);break;}
}
return 0;
}
/*
9
5 2 1 5 2 1 5 2 1
*/