题目链接:点击打开链接
比赛的时候老是想搜索加构造长度,以分的份数来搜,由于构成相等长度的长木棍
不一定是相等的份数,自然思路混乱,想不出来。
如果是以长度来分就好办了。
先将所有的木棍降序排列。
1、首先 要求的能拼成的长木棍的最小长度len 一定是 大于等于a[0],小于所有木棍的
总长度s的。并且len一定能整除sum。
2、剪枝:
No.1------如果某木棍长度不满足,则其后与它相同长度的木棍可以直接跳过。
No.2------如果新一轮的开始 和 当前的长度恰好填满剩下的长度,但是后面的搜索失败,则返回false。
我这题又碰到G++提交RE,C++提交AC了。
原来是 将 cmp函数 写成
bool cmp(int x,int y){
return x>=y;
}
但事实上不能带等号。
不然 这组数据过不了------
64
50 50 50 。。。50(全是50)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int a[69];
int vis[69];
int n;
bool cmp(int x,int y)
{
return x>y;
}
bool dfs(int l,int s,int cnt)
{
if(l==s && cnt==n) return true;
if(l==s) l=0;
for(int i=0;i<n;i++)
{
if(!vis[i] && a[i]+l<=s)
{
vis[i]=true;
if(dfs(a[i]+l,s,cnt+1))
return true;
vis[i]=false;
if(l==0 || l+a[i]==s) //剪枝2
return false;
while(i+1<n && a[i+1]==a[i]) //剪枝1
i++;
}
}
return 0;
}
int main()
{
int i,s,len;
while(scanf("%d",&n)!=EOF && n)
{
memset(a,0,sizeof(a));
for(i=0,s=0;i<n;i++)
{
scanf("%d",&a[i]);
s+=a[i];
}
sort(a,a+n,cmp);
for(len=a[0];len<s;len++)
{
if(s%len==0)
{
memset(vis,0,sizeof(vis)); //每次都要标记清0
if(dfs(0,len,0))
break;
}
}
printf("%d\n",len);
}
return 0;
}