DFS之剪枝与优化 AcWing 167. 木棒
原题链接
算法标签
搜索 剪枝
思路
由于不知道原始木棒的长度len,但知道每根小木棍的长度,小木棒最长的时候就是一根的时候也就是长度等于所有的小木棍的长度总和sum。所以,我们可以枚举长度len。就把查询问题转化成了判断该长度是否可行的问题。
确定长度的同时也就确定了小木棒的数量cnt为sum/len,就可以作为合法标志的判断条件:在所有的小木棍都用完的情况下拼成了cnt个长度相等的小木棒。
剪枝
代码
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define x first
#define y second
#define ump unordered_map
#define pq priority_queue
#define rep(i, a, b) for(int i=a;i<b;++i)
#define Rep(i, a, b) for(int i=a;i>b;--i)
using namespace std;
typedef pair<int, int> PII;
const int N = 70;
//int t, n, m, cnt, ans;
int sum=0, length, n;
int w[N];
bool st[N];
inline int rd(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put(int x) {
if(x<0) putchar('-'),x=-x;
if(x>=10) put(x/10);
putchar(x%10^48);
}
// 从start开始的第u根木棒 木棒长度为cur
bool dfs(int u, int cur, int start){
if(u*length==sum){
return true;
}
// 木棒长度为length 开辟第u+1个新木棒
if(cur==length){
return dfs(u+1, 0, 0);
}
// 剪枝3-1 从start寻找符合条件的木棍
rep(i, start, n){
//cur+st[i]>length 可行性剪枝
if(st[i]||cur+st[i]>length){
continue;
}
st[i]=true;
if(dfs(u, cur+w[i], i+1)){
return true;
}
st[i]=false;
// !cur 剪枝3-3
// cur+w[i]==length 剪枝3-4
if(!cur||cur+w[i]==length){
return false;
}
// 剪枝3-2
int j=i;
while(j<n&&w[i]==w[j]){
j++;
}
i=j-1;
}
return false;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
while(scanf("%lld", &n), n){
memset(st, 0, sizeof st);
sum=0;
rep(i, 0, n){
w[i]=rd();
sum+=w[i];
}
sort(w, w+n);
reverse(w, w+n);
length=1;
while(true){
if(sum%length==0&&dfs(0, 0, 0)){
printf("%lld\n", length);
break;
}
length++;
}
}
return 0;
}
参考文献
AcWing 167. 木棒(算法提高课)y总视频讲解
原创不易
转载请标明出处
如果对你有所帮助 别忘啦点赞支持哈