您的位置:首页 > 其它

POJ1011 DFS+剪枝

2017-09-03 19:13 375 查看
题意

乔治有一堆相同长度的木棍,随意切割。这时他想要将这些切割后的短棍复原成若干条相同长度的木棍。求复原后木棍的最小长度。

思路:

1、答案只可能是木棍总长的约数,且不小于最长短棍的长度,则可将问题转化为熟悉的求和问题。

2、将长度降序排列,有利于剪枝。

3、具体剪枝看代码注释。

反思

1、没有想到第一点。

2、剪枝还需强化。

代码

#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN = 70;
priority_queue<int, vector<int>, greater<int> > divisor;
int n, total, _max;
int stick[MAXN], add[MAXN];
bool vis[MAXN];
bool cmp(int a, int b)
{
return a > b;
}
void Find()
{
for(int i = 1; i * i <= total; i++)
{
if(total % i == 0)
{
if(i >= _max) divisor.push(i);
if(i != (total/i) && (total/i) >= _max) divisor.push(total/i);
}
}
}
void Add()//剪枝1 利用后缀和
{
add
= stick
;
for(int i = n - 1; i >= 1; i--)
{
add[i] = add[i + 1] + stick[i];
}
}
bool DFS(int target, int tempTarget, int pos, int used)
{
vis[pos] = true;
if(tempTarget == 0 && used == n)
{
printf("%d\n", target);
return true;
}

if(tempTarget == 0 && used != n)
{
if(DFS(target, target, 0, used)) return true;
else return false;
}
if(pos == 0)//剪枝2 如果是重新拼一根新的木棍,第一根可用且最长的短棍无法DFS成功,这根便永远也无法用上了。
{
for(int i = 1; i <= n; i++)
{
if(tempTarget >= stick[i] && !vis[i] && tempTarget <= add[i])
{
if(DFS(target, tempTarget - stick[i], i, used + 1)) return true;
else
{
vis[i] = false;
return false;
}
}
}
}
else
{
for(int i = pos + 1; i <= n; i++)
{
if(tempTarget >= stick[i] && !vis[i] && tempTarget <= add[i])
{
if(!vis[i - 1] && stick[i] == stick[i - 1]) continue;//剪枝3 最重要的剪枝,防止在同一层面进行无意义的重复搜索
if(DFS(target, tempTarget - stick[i], i, used + 1)) return true;
else
{
vis[i] = false;
}
}
}
}
return false;
}
int main()
{
while(scanf("%d", &n) && n)
{
total = 0;
memset(vis, false, sizeof(vis));
while(!divisor.empty()) divisor.pop();

for(int i = 1; i <= n; i++)
{
scanf("%d", &stick[i]);
total += stick[i];
}
sort(stick + 1, stick + 1 + n, cmp);
_max = stick[1];
Find();
Add();
while(!divisor.empty())
{
if(DFS(divisor.top(), divisor.top(), 0, 0)) break;
else
{
divisor.pop();
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM