首页 > 代码库 > poj 1011 Sticks 【DFS】+【剪枝】
poj 1011 Sticks 【DFS】+【剪枝】
题意:有未知根(长度一样)木棒(小于等于n),被猪脚任意的截成n段,猪脚(脑抽了)想知道被截之前的最短长度(我推测猪脚得了健忘症)。
这道题光理解题意就花了好久,大意就是任意根被截后的木棒拼到一起,能不能组成s(《=n)根的相同的木棒,
例:数据 9
5 1 2 5 1 2 5 1 2
可以组成最短为6 的(5+1, 2+2+2)3根木棒。
策略:深搜。
不过要是传统的深搜的话,TLE妥妥的。所以要剪枝(所谓剪枝,就是多加几个限制条件)。
话不多说直接上代码。
代码1:
#include <stdio.h> #include <string.h> #include <algorithm> using std::sort; int s[70], n;//n是被截成的段数 bool vis[70]; int cmp(int a, int b) { return a > b; } int dfs(int len, int cur, int num) //len是假设的答案,cur是构成答案长度的木棒所需要的,num,是剩余的木棒数 { if(cur ==0&&num ==0) return true; //如果都满足条件,果断返回true if(cur == 0) cur =len; //如果满足了一根木棒,那么就继续构成下一根木棒(剪枝) int i; for(i = 0; i < n; i ++){ if(vis[i]) continue; if(cur - s[i] >= 0){ vis[i] = 1; if(dfs(len, cur-s[i], num-1)) return true;//如果构不成,果断返回false(剪枝) vis[i] = 0; if(s[i] == cur||cur == len) return false;//s[i]==cur是如果满足一根木棒的长度但是不能构成全部的,cur == len 是进行循环之后还是构不成 都要返回false(剪枝) while(s[i] == s[i+1]&&i+1 < n) ++i;//如果同等长度的不满足,就不用再继续该长度的了(剪枝) } } return false; } int main() { int i; while(scanf("%d", &n), n){ int sum = 0; for(i = 0; i < n; i ++){ scanf("%d", &s[i]); sum += s[i]; } sort(s, s+n, cmp);//从大到小排序,对于程序更快,比如说因为我们考虑4的时候,如果4不满足构成满足条件的木棒,那么1和3组合肯定也不满足条件,那么我们4不满足条件的时候,我们就可以结束这次深搜了。 for(i = s[0]; i <= sum; i ++){ //最大不可能超过总和,最小得大于这么多最长的 if(sum %i == 0){ memset(vis, 0, sizeof(vis));//每一次都要初始化 if(dfs(i, 0, n)){ printf("%d\n", i); break; } } } } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。