题意简单说就是本来几根一样长的棍子 被小明乱切(乱切 没切中也是有可能的) 切成了n根小棍子
要你把n根小棍子恢复原样 可能有多组解
要求输出 每根棍子最短的情况时 棍子长度
据说是极为经典的dfs题
一开始真的不知道怎么搜好(辣鸡无力)闷了1个多小时无奈去看了一下题解 恍然大悟
看完自己敲一A后 细看一下 还是原来那些东西 dfs传参 之前积累的棍长 棍的数量 累加棍的位置
AC Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <stack>
using namespace std;
int stick[70];
bool flag[70];
int len,sum,num,n;//len 棍长 sum所有棍子总长度 num棍数目 n小棍数目
bool dfs(int pre_len,int pre_num,int pos)
{
if(pre_num==num) return true;
for(int i=pos;i<n;i++)
{
if(flag[i]) continue;
if(pre_len+stick[i]==len)
{
flag[i]=true;
if(dfs(0,pre_num+1,0)) return true;
flag[i]=false;//回溯
return false;
}
else if(len>(pre_len+stick[i]))
{
flag[i]=true;
if(dfs(pre_len+stick[i],pre_num,i+1)) return true;
flag[i]=false;
if(pre_len==0) return false;//这时 之前一根棍都没有 len>stick[i]
while(i+1<n&&stick[i]==stick[i+1]) i++;//相邻一样的情况就不用算了
}
}
return false;
}
int main()
{
while(scanf("%d",&n),n)
{
num=sum=0;
for(int i=0;i<n;i++)
{
scanf("%d",&stick[i]);
sum+=stick[i];
}
sort(stick,stick+n,greater<int>());
memset(flag,false,sizeof flag);
for(len=stick[0];len<=sum;len++)
{
if(sum%len) continue;//必须整除
num=sum/len;//总共棍子的数量
if(dfs(0,0,0))
{
printf("%d\n",len);
break;
}
}
}
return 0;
}