Sticks
题目传送门。
题目大意是,给你一个数字n代表总共的棍子数量,要做的就是,把这几根棍子拼成长度相同的棍子,并且让所拼成的棍子的长度尽可能地小,也就是拼成的棍子的数量尽可能的多。
在这里很简单的想到要给棍子排一下序,这样可以更简单找到合适棍子的。
-------------------下面的代码除去注释就是我自己写的代码。----------------------
#include<iostream>
#include<cstring>
#include<algorithm>
const int maxn=70;
int a[maxn],visit[maxn];
int n,total,target;
using namespace std;
bool dfs(int sum,int len,int pos) {
if(sum==total) return true;
if(len==target) return dfs(sum+1,0,0);
for(int i=pos;i<n;i++) {
if(!visit[i]&&len+a[i]<=target) {
visit[i]=1;
if(dfs(sum,len+a[i],i+1)) return true;
visit[i]=0;
// if(len==0) return false;
// while(i+1<n&&a[i+1]==a[i]) i++;
}
}
return false;
}
int main()
{
freopen("D:\\MY\\ce.txt","r",stdin);
while(cin>>n&&n) {
int sum=0,ans=0;
memset(a,0,sizeof(a));
memset(visit,0,sizeof(visit));
for(int i=0;i<n;i++) {
cin>>a[i];
sum+=a[i];
}
sort(a,a+n,greater<int>());
for(int i=a[0];i<=sum;i++) {
if(sum%i==0) {
total=sum/i;
target=i;
if(dfs(0,0,0)) {
ans=i;
break;
}
}
}
cout<<ans<<endl;
}
return 0;
}
这段注释就是这个代码的灵魂所在,
没有这一段能在样例中跑出超时,
但是有这一段代码轻轻松松就跑完了所有样例。
但是这个代码的精髓就是:
第一步if剪枝:
会进入当len==0的时候这里就代表着,有一根棍子找了一圈发现找不到满足条件的,然后回到main函数里的for循环,尝试下一个target。
第二步while剪枝:
单现在查找的target有可能时正确答案时,对len不为0的情况,就是当前尝试的棍子不符合条件,所以当前长度的棍子可以不用再试了,换别的棍子继续尝试。