hdu 1455 Sticks(DFS+剪枝)

来源:互联网 发布:js 字符串等于 编辑:程序博客网 时间:2024/06/05 00:28

hdu 1455 : http://acm.hdu.edu.cn/showproblem.php?pid=1455

这道题是大一学习dfs时学习的,但是发现自己现在还是不会写,写着写着超时了。主要是两个剪枝想不到了,代码中给注释了。网上也有好多这道题的做法,我不多说了。

用的是没有返回值的dfs。

剪枝1:答案必须是sum的约数。

剪枝2:从大到小排序减小递归深度。

剪枝3:例如某个组合用到4,原序列中有4也有3,1,那么优先使用4,因为3,1的用处更大,就是代码中的break剪枝。

剪枝4:最重要的剪枝,第一个数一定要能够组成。

#include <algorithm>#include <cstdio>#include <cstring>using namespace std;int sticks[65];bool vis[65];int n, sum;bool flag = false;int cmp(const int a, const int b) {    return a > b;}// 最怕不写dfs参数注释的人了。。。。// pos寻找可用木棍的开始位置,avg原始木棍的长度,// cnt表示已经凑得的原木棍数,add正在组合的木棍长度void dfs(int pos, int avg, int cnt, int add) {    if(cnt == sum / avg || flag == 1) {        flag = 1;        return ;    }    for (int i = pos; i < n; i ++) {        if(!vis[i]) {            if(add + sticks[i] == avg) {                vis[i] = 1;                dfs(0, avg, cnt + 1, 0);                vis[i] = 0;                break;  // 如果大的数能够使用,小的数也能使用,优先使用大的数。            } else if(add + sticks[i] < avg) {                if(i > 0 && !vis[i-1] && sticks[i] == sticks[i-1]) {                    continue;                }                vis[i] = 1;                dfs(i + 1, avg, cnt, add + sticks[i]);                vis[i] = 0;            }            // 第一根木棍一定能够组成一组,这个剪枝从TLE到0ms            if(pos == 0) {                return ;            }        }    }}int main() {    while (~scanf("%d", &n), n) {        sum = 0, flag = false;        for (int i = 0; i < n; i ++) {            scanf("%d", sticks + i);            sum += sticks[i];        }        sort(sticks, sticks + n, cmp);        for (int i = sticks[0]; i <= sum / 2; i ++) {            if(sum % i == 0) {                memset(vis, 0, sizeof(vis));                dfs(0, i, 0, 0);                if(flag == 1) {                    printf("%d\n", i);                    break;                }            }        }        if(flag == 0) {            printf("%d\n", sum);        }    }    return 0;}



0 0
原创粉丝点击