POJ 1011 Sticks 解题报告

来源:互联网 发布:嵌入式网络研发 编辑:程序博客网 时间:2024/05/08 04:37

参考(其实是完全移植了)这里的解题报告:http://blog.sina.com.cn/s/blog_6635898a0100lgq0.html。

感觉搜索题做伤了。短期之内不会再做了。

首先,sticks要从大到小排序。因为大的stick相对难找,一开始就确定好有利于更快地确定解。

其次,记下当前正在匹配的stick,下次从这个stick之后开始试。

再次,如果当前的stick和前一个stick的长度一样,而前一个stick没有选(前一个stick肯定一个尝试过了,没选是因为没有解),说明这个stick也不用尝试了。

个人认为要点在于链接中的第3点,即如果当前len等于0,即(匹配完了上一段或最开始),新开始一段时,只需要取第一个没选的(也是最大的,因为sticks已经从大到小排序好了。)。不用再像普通循环里面的那样,一个一个尝试了。因为如果有解,这个第一个stick迟早要选,而且位置在哪里都不关心,所以第一个选它就可以了。

code已经改得和链接上面几乎完全一样了。这里为了日后记录,遂粘贴与此。

#include <algorithm>#include <iostream>using namespace std;const int MAXN = 65;int N, len;int sticks[MAXN];bool mark[MAXN];bool flag;void recur(int depth, int l, int k){if(flag){return;}if(l == 0){int i = 0;while(mark[i]){i++;}mark[i] = true;recur(depth + 1, sticks[i], i + 1);mark[i] = false;return;}if(l == len){if(depth == N){flag = true;}else{recur(depth, 0, 0);}return;}for(int i = k; i < N; i++){if(!mark[i] && l + sticks[i] <= len){if(!mark[i - 1] && sticks[i - 1] == sticks[i]){continue;}mark[i] = true;recur(depth + 1, l + sticks[i], i + 1);mark[i] = false;}}}int main(){while(scanf("%d", &N) && N != 0){flag = false;int sum = 0;for(int i = 0; i < N; ++i){fscanf(stdin, "%d", &sticks[i]);sum += sticks[i];// fprintf(stdout, "sticks[%d]: %d\n", i, sticks[i]);}sort(sticks, sticks + N, greater<int>());for(len = sticks[0]; len <= sum; ++len){if(sum % len == 0){// memset(mark, false, N * sizeof(bool));memset(mark, false, sizeof(mark));recur(0, 0, 0);if(flag){fprintf(stdout, "%d\n", len);break;}}}}return 0;}


原创粉丝点击