您的位置:首页 > 其它

POJ 1011 Sticks(dfs+剪枝)

2017-01-23 09:21 429 查看
http://poj.org/problem?id=1011

题意:若干个相同长度的棍子被剪成若干长度的小棍,求每根棍子原来的可能最小长度。

思路:很经典的搜索题。

我一开始各种超时,这题需要很多剪枝。

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;

int n;
int a[70];
int vis[70];

bool cmp(int a, int b)
{
return a > b;
}

int dfs(int len, int left_len, int number) //棍子长度、还需要匹配长度、未匹配棍子数量
{
if (left_len == 0 && number == 0)  return len;   //所有棍子已全部匹配完毕
if (left_len == 0)  //已匹配完一根棍子
left_len = len;
for (int i = 0; i < n; i++)
{
if (!vis[i] && a[i] <= left_len)
{
vis[i] = 1;
if (dfs(len, left_len - a[i], number - 1))  //深搜
return len;
vis[i] = 0;
if (left_len == a[i] || len == left_len)  break; //剪枝,没有数可以和当前值匹配,直接跳出循环
while (a[i] == a[i + 1]) i++;  //剪枝,如果后面和前面一样,则跳过
}
}
return 0;
}

int main()
{
//freopen("D:\\txt.txt", "r", stdin);
while (cin >> n && n)
{
memset(vis, 0, sizeof(vis));
int sum = 0;
int maxn = 0;
for (int i = 0; i < n; i++)
{
cin >> a[i];
sum += a[i];
//if (a[i]> maxn)  maxn = a[i]; //记录长棍子,dfs时从最长棍子开始
}
int k = 0;
sort(a, a + n,cmp);
for (int i = a[0]; i <= sum; i++)
{
if (sum%i == 0)  //剪枝,不能除尽说明棍子长度不能为i
{
k = dfs(i, 0, n);
if (k) break;
}
}
cout << k << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: