题目
http://codevs.cn/problem/3498/
题解
假设所有数的和为s,那么答案ans一定满足ans|s,因此从小到大枚举s的因子,验证所有木棍能否被分成s/ans组,每一组的和为ans。
现在的问题就成了验证性问题。
思路一:设s/ans个桶,每个桶的容量为ans,然后暴力枚举每根小木棍应该放进哪个桶,加各种优化70分。
思路二:玄学,我也不知为什么正确。把所有木棍按长度从大到小排序,暴力选择s/ans次,每次选出前几个能组成ans的木棍,打上访问标记。5ms过。
代码
#include <cstdio>
#include <algorithm>
using namespace std;
int chosen[100], N, l[100], ans, s;
bool dfs(int pos, int left)
{
if(left==0)return true;
if(left<0)return false;
if(pos>N)return false;
if(chosen[pos])return dfs(pos+1,left);
if(dfs(pos+1,left-l[pos]))return chosen[pos]=true;
return dfs(pos+1,left);
}
bool cmp(int a, int b){return a>b;}
int main()
{
int i;
scanf("%d",&N);
for(i=1;i<=N;i++)scanf("%d",l+i),s+=l[i];
sort(l+1,l+N+1,cmp);
for(ans=l[1];ans<=s;ans++)
{
if(s%ans)continue;
for(i=1;i<=N;i++)chosen[i]=0;
for(i=1;i<=s/ans;i++)dfs(1,ans);
for(i=1;i<=N;i++)if(chosen[i]==0)break;
if(i>N)break;
}
printf("%d\n",ans);
return 0;
}