Poj 1014简单dfs

来源:互联网 发布:淘宝爆款是什么意思 编辑:程序博客网 时间:2024/05/22 04:37

传送门:POJ1014

题意:给你1-6六个数,分别有不一定的数量,问你能不能凑成和相等的两部分。

其实这个题真的很水啊,真的真的很水啊,可是月赛的时候愣是让三个人TLE的一晚上,想尽办法剪枝,又剪成了WA。。最后赛完发现是回溯的问题。。。这题根本不用回溯。。带上回溯必定超时,不回溯的原因是:dfs的时候已经保证了每次加入一个新数时不能超过sum/2,所以只需要一口气搜到底就好了,如果这次拼不成,就算再回溯也肯定拼不成,这里做个假设要拼凑的数为sum/2==30,那么前18用越大的数来拼越好(优先级6>5>4...),因为较小的数要留下来处理边界情况,后12数越小边界情况越有可能处理成功,因此如果回溯用另外一些小的数去拼凑这里的18,后面就更不可能拼成了。

理解不了也可以感性思考一下,因为我们是去dfs拼凑两部分之一,那么这一堆里没有的数就是要扔给另一堆的,你这一堆用这些数都拼不成,在回溯的时候把这些数扔给另一堆,那另一堆肯定也拼不成啊。。

写这篇博客来纪念一下一晚上的TLE吧。。

下面是正确代码:

#include<stdio.h>#define n 6int sum;int num[6],k=0,flag;int dfs(int s)//s是已经凑出来的数的和{if(s==sum||flag){flag=1;return 0;}for(int i=5;i>=0;i--){if(num[i]&&(s+i+1)<=sum){num[i]--;dfs(s+(i+1));if(flag)return 0;}//千万不要回溯}}int main(){int i;while(~scanf("%d",&num[0])){flag=0;sum=0;k++;for(i=1;i<6;i++)scanf("%d",&num[i]);for(i=0;i<6;i++){sum+=num[i]*(i+1);}if(sum==0)break;printf("Collection #%d:\n",k);if(sum%2==0){sum/=2;dfs(0);if(flag)printf("Can be divided.\n");elseprintf("Can't be divided.\n");}else{printf("Can't be divided.\n");}printf("\n");}}


0 0
原创粉丝点击