Stick ------ 剪枝神题
2016-03-29 21:23
489 查看
这个是自己剪得 , 我感觉已经很不错了 但是不知道哪里出了问题 一直 超时
// 根据所给答案 和 题目要求 最直观的就可以有剪枝的地方 而且 剪枝剪得越早 就越省时省力 // 好的思路也可以省不少的时间 #include<stdio.h> #include<string.h> #include<math.h> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<set> #include<stack> #include<string> #include<sstream> #include<map> #include<cctype> using namespace std; bool cmp(int a,int b) { return a>b; } int a[55],goal,visited[55],mark,result,sum,n,flag; void DFS_check() // 我感觉 前面的两个剪枝 就十分的强悍了 但是鉴于 这一道题 比较的 变态 所以 继续剪枝! { if(flag) return ; if(goal>result) return ; if(goal==result) // 加上了最后一个数字 这时候 mark 也刚刚好 所以 这个放上面 { mark++; goal=0; // 攒够 一套之后 就直接让 计数器归零 } if(mark*result==sum)// 这时候 是 刚好符合条件 // 这个值 不可能大于 sum { flag=1; } for(int i=0;i<n;i++) { if(!visited[i]) // 没有被访问过 { visited[i]=1; goal+=a[i]; DFS_check(); goal-=a[i]; visited[i]=0; while(a[i]==a[i+1]) i++; } } if(flag) return ; } int main() { while(scanf("%d",&n),n) { result=sum=0; for(int i=0;i<n;i++) { scanf("%d",&a[i]); sum+=a[i]; } sort(a,a+n,cmp); // 将 碎木棒长度 从大到小排序之后 1 :方便操作 2 :在找出答案之后 可以很快的退出 寻找 ,能省不少的时间 int len=(sum/2)+1; for(int i=a[0];i<=len;i++) // 一个剪枝 , 这个估计能省去 理论上一半的时间 的时间 { if(sum%i!=0) // 这里的 i 是假设的 原始木棒长度 // 如果总长度 不能被假设木棒长度整除的话 , 这个假设就是不成立的 . continue; memset(visited,0,sizeof(visited)); flag=goal=mark=0; result=i; DFS_check(); if(flag) // 检查 该长度 是否 是 最小的木棒长度 { result=i; //更新最小木棒长度 break; } } if(result==0) result=sum; printf("%d\n",result); } return 0; }
下面附上正确答案
#include<stdio.h> #include<string.h> #include<math.h> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<set> #include<stack> #include<string> #include<sstream> #include<map> #include<cctype> using namespace std; int n,sum,a[100],goal,visited[100]; bool cmp(int a,int b) { return a>b; } bool DFS(int now,int index,int mark,int goal) // mark 已集齐的 原始木棒数量 goal 假设原始木棒长度 { if(mark*goal==sum) return true; for(int i=index;i<n;i++) { if(visited[i]||(a[i]==a[i-1]&&!visited[i-1])) //如果这一个节点 已经 被用了 就不再用了 //如果这个节点和上一个节点相同 并且上一个节点 没有被使用 那么这个节点就也不会被使用了 continue; // 因为 出现这种情况 的原因只有一种就是 + 这个数值 now 大于了 目标值 if(now+a[i]==goal) { visited[i]=1; if(DFS(0,0,mark+1,goal)) return true; visited[i]=0; return false; } else if(now+a[i]<goal) { visited[i]=1; if(DFS(now+a[i],i+1,mark,goal)) // 在已经确定了一个比较大的值之后 继续向后面寻找比较小的值 return true; visited[i]=0; if(now==0) return false; } } return false; } int main() { while(scanf("%d",&n) == 1 && n) { int i; for(i=sum=0;i<n;i++) { scanf("%d",&a[i]); sum+=a[i]; } sort(a,a+n,cmp); for(i=a[0];i<sum;i++)// 开始从最长的假设 { if(sum%i) //如果不能整除的话 那一定不是 原始 平均长度 continue; memset(visited,0,sizeof(visited)); if(DFS(0,0,0,i)) { printf("%d\n",i); break; } } if(i==sum) printf("%d\n",sum); } return 0; }
相关文章推荐
- 分布式事务最终一致性常用方案
- [SIMD]单指令多数据指令集(二)—— SIMD指令集在非对称算法中的应用
- Unity Shaders and Effects Cookbook (2-7)实现 Photoshop 色阶效果
- hdu4786-图论训练3-最小生成树
- 设计模式:装饰模式(Decorator)
- 【Coursera】Machine learning - week6 : Advice for Applying Machine Learning
- 机器学习中的数学(5)-强大的矩阵奇异值分解(SVD)及其应用
- 设计模式:装饰模式(Decorator)
- 对象转型实例扩展
- Java数据结构——优先级队列
- 作业4.2:结对项目—— 词频统计(第二阶段)
- 3.26 项目质量管理、人力资源管理
- 服务器维护系列——VNC没有反应了怎么办?
- Gson用法一
- C#.Net 图片处理大全
- Dynamics CRM2016 Web API之Retrieve Multiple
- Dynamics CRM2016 Web API之Retrieve Multiple
- Dynamics CRM2016 Web API之Retrieve Multiple
- Dynamics CRM2016 Web API之Retrieve Multiple
- ThreadLocal源码分析