您的位置:首页 > 其它

POJ 1011 Sticks

2015-05-11 14:11 453 查看
传说中的入门级经典DFS搜索+剪枝,果然一看答案就会了

。。。

因为不存在顺序问题,当不符合条件时长棍更容易检测出来,所以从大到小排列。

朴素的DFS搜索:

int dfs( int temp_sum, int remain, int num){
int i;
if( remain == 0){
if( num == 0) return 1;
else remain = temp_sum;
}
for( i = 0; i < n; i++){
if( vis[i] == 0){
if( remain >= a[i]){
vis[i] = 1;
if( dfs( temp_sum, remain-a[i], num-1)) return 1;
vis[i] = 0;
}
}
}
return 0;
}


剪枝思路:

① 原最小棍长一定是总和的因数

② 如果棍长不符合当前所有棍的和,就放弃搜索

③ 相等棍长的棍只用搜索一次

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int cmp( const void* a, const void* b){                          // 从大到小排列
return *(int*)b - *(int*)a;
}
int ans, n;
int a[100], vis[100];

int dfs( int temp_sum, int remain, int num);
int main(void){
int i, sum;

while( scanf("%d", &n)!= EOF && n){
sum = 0;
for( i = 0; i < n; i++){
scanf("%d", &a[i]);
sum += a[i];                           // 在这里求所有棍长的和
}
qsort( a, n, sizeof(int), cmp);
memset( vis, 0, sizeof(vis));                   // 把访问数组设置为0
for( ans = 2; ans < sum; ans++){
if( sum % ans) continue;                // 剪枝1:原最小棍长一定是总和的因数
else if( dfs( ans, ans, n)) break;
}
printf("%d\n", ans);
}
return 0;
}
int dfs( int temp_sum, int remain, int num){                    // 参数设置:暂时的棍长用来试验,余下的长度,余下的棍数
int i;
if( remain == 0){                                       // 满足了一次棍长
if( num == 0) return 1;                         // 若此时所有的木棍都被用过,则此时的棍长满足题意,返回成功
else remain = temp_sum;                         // 否则重置剩余棍长,继续试验
}
for( i = 0; i < n; i++){                                // 从第0根木棍开始试验
if( vis[i] == 0){                               // 只试验未被访问的棍
if( remain >= a[i]){                    // 若此时棍长小于剩余棍长
vis[i] = 1;                     // 假设使用
if( dfs( temp_sum, remain-a[i], num-1)) return 1;   // 继续向下搜索,若满足条件停止搜索
vis[i] = 0;                                         // 所有搜索都不满足条件,则此木棍不在当前组合中
if( a[i] == remain || remain == temp_sum) break;    // 剪枝2:若没有符合条件的木棍,说明当前棍长不符合条件,认为失败,停止搜索
while( a[i] == a[i+1]) i++;                         // 剪枝3:如果随后的木棍和此木棍相同长度,则跳过不搜索
}
}
}
return 0;                                               // 返回失败
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: