poj 1011 Sticks 减枝搜索
题意
有N根棍子,分别有长度。问将其拼接成X根,长度相同,求最小长度。
解法
搜索。
1.因为总共n根棍子,最多拼接成n根相同长度, 并且,组成的棍子数量越多,则长度则越小
2.拼接的棍子数量必定能够 被 \sum{stick_i} 整除
3.若当前棍子长度 stick_i 不能够匹配, 在 stick_i = left_len 或者 stick_i = target_len 情况下, 此
长度无合法方案, 因为每一根棍子都将被使用,若有一根不能被使用,则此长度方案必定不能成立.
View Code
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; #define MAX(a,b) (a)>(b)?(a):(b) int a[110], n; bool vis[110]; bool dfs( int use, int left, int A ){ if( use == 0 && left == 0 ) return true; if( left == 0 ) left = A; for(int i = 0; i < n; i++){ if( vis[i] ) continue; if( a[i] > left ) continue; vis[i] = 1; if( dfs( use-1, left-a[i], A ) ) return true; vis[i] = 0; // use a[i] is failure if( a[i] == left || left == A ) break; } return false; } int compare( int a, int b ){ return a > b; } int main(){ while( scanf("%d", &n), n ){ int sum = 0; for(int i = 0; i < n; i++){ scanf("%d", &a[i] ); sum += a[i]; } sort( a, a+n, compare ); int ans; memset( vis, 0, sizeof(vis)); for( int A = n; A > 0; A--){ if( (sum%A == 0) && (sum/A >= a[0]) ){ if( dfs( n, 0, sum/A ) ){ printf("%d\n", sum/A); break; } } } } return 0; }