首页 > 学院 > 开发设计 > 正文

Uva307 Sticks 【dfs+剪枝】【习题7-14】

2019-11-08 02:10:36
字体:
来源:转载
供稿:网友

题目:Sticks

题意:起初有一些相等的木棍,然后被人砍成了n个木条。长度分别给出,现在需将n个木条组合拼成回原来的木棍,问原始木棍的最小可能长度?

思路:虽然知道用dfs,但没想到怎么实现多个相等的判断,然后参考了后做的,其实还是那些套路,就是变通不了。。。不过这个剪枝比较NB。。。

(1)枚举:枚举原始木棍长度,从总长度/i   i时n~1

(2)搜索:枚举给出的数组,枚举位置不是每次都从0开始,而成在递归中的pos参数,每次是从上一个的下一位开始的,递归中累加上木棍长度,当长度符合枚举的原始木棍长度时,再继续搜索,但是参数需要改变,pos从0开始,sum木棍长度也从0开始,当个数继续+1,当个数与n相等时所有所有木条都组合拼成木棍了。

(3)剪枝:

①递减排序,可以递归层数;

②枚举原木棍长度应是总长度的倍数且大于最达的木条长度,其他的没有必要搜索,因为根本达不到!

③当搜索时第i个木条时,第i个木条还未选(即放在还原标记数组的后面)时,如果后面的长度和i的相等,就没有必要再枚举,直接i++;(有点懵)

④当第i个木条没有找到时,没有必要再继续寻找了,直接return剪枝。(还是有点懵!)

注意:以后判断标记数组时用if(visit[i]) continue;  不能和有条件的判断中加 !visit[i] 这样时间会很慢!

参考:JeraKrs博客

代码:

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int maxn = 100 + 5;bool cmp(int a,int b){return a > b;}int n,stick[maxn],visit[maxn];int ans,len;bool dfs(int steps,int pos,int sum){    if(steps == n) return true;//当到达第n个,说明所以木条都组合拼成了    for(int i = pos;i < n;i++){        if(visit[i]) continue;//关键,访问过的跳过        if(sum + stick[i] < ans){            visit[i] = 1;            if(dfs(steps+1,i+1,sum + stick[i])) return true;            visit[i] = 0;            while(stick[i] == stick[i+1] && i+1 < n) i++;//剪枝:当i个数和第i+i数相等时,不需要再枚举,因为依然小于ans        }        else if(sum + stick[i] == ans){            visit[i] = 1;            if(dfs(steps+1,0,0)) return true;//当达到组合值时,将组合木条长度和下标位置归为0,继续搜索,因为是几个相等的木条,所以不是找到一个就行。。。            visit[i] = 0;            return false;        }        if(sum == 0) return false;//剪枝:当上面都没有return时,程序会走到这一步,说明第i个木条没有找到合适的组合,直接return     }        return false;}inline int solve(){    for(int i=n;i>=0;i--){//从大到小分        if(len % i == 0 && len / i >= stick[0]){//总长度的倍数且平分长度大于初始的最长木条才可进行组合            memset(visit,0,sizeof(visit));            ans = len / i;//当前组合长度            if(dfs(0,0,0)) return ans;        }    }    return -1;}int main(){    while(scanf("%d",&n)!=EOF && n){        len = 0;        for(int i=0;i<n;i++){            scanf("%d",&stick[i]);            len += stick[i];        }        sort(stick,stick+n,cmp);//递减排序        PRintf("%d/n",solve());    }    return 0;}


上一篇:qt 问题

下一篇:二分搜索及测试函数

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表