dfs拼木棒,剪枝
这题对dfs效率要求比较高,起初乱七八糟的代码果断TLE了。一般来说,dfs时能判断的尽量在上层进行判断,不要带到下层去判断。而且在这题中,如果相连的同样长的小棒不再同样搜索,这点很重要~~~~~~~
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int num[70], n, g_sum, len; bool mark[70]; bool dfs( int deep, int pos, int sum ) { int i; if( sum == len ) { if( deep+1 == g_sum/len ) return 1; for(i=n-1; i>=0; --i ) if( !mark[i] ) break; mark[i] = 1; if( dfs( deep+1, i-1, num[i] ) ) return 1; mark[i] = 0; } else { if( pos < 0 ) return 0; for( i=pos; i>=0; --i ) { if( mark[i] || sum + num[i] > len) continue; if( num[i] == num[i+1] && !mark[i+1] ) continue; //很膜拜这个剪枝。相连的同样长的小棒不再同样搜索 mark[i] = 1; if( dfs( deep, i-1, sum+num[i] ) ) return 1; mark[i] = 0; } } return 0; } bool solve() { int i; if( num[n-1] > len ) return 0; memset( mark, 0, sizeof(mark) ); mark[n-1] = 1; if( dfs( 0, n-1, num[n-1] ) ) return 1; mark[n-1] = 0; return 0; } int main() { // freopen( "c:/aaa.txt", "r", stdin ); int i; while( scanf("%d", &n), n) { g_sum = 0; for( i=0; i<n; ++i ) { scanf( "%d", &num[i] ); g_sum += num[i]; } sort( num, num+n ); for( i=n; i>=2; --i ) { if( g_sum % i != 0 ) continue; len = g_sum / i; if( solve() ) break; } printf( "%d\n", g_sum/i); } return 0; }
类似的题还有hdoj 1518 Square
题目要求用所给长度不一的木棍拼出一个正方形,问行不行。同样剪枝能关键,长度相同的木棍不用判断两次~~~~~
#include <iostream> #include <algorithm> using namespace std; int n, num[25]; int maxx, half, len; bool mark[25]; bool dfs( int deep, int cur, int sum ) { int i; if( sum == len ) { if( deep + 1 == 4 ) return 1; for( i=n-1; i>=0; --i ) if( !mark[i] ) break; mark[i] = 1; if( dfs( deep+1, i, num[i] ) ) return 1; mark[i] = 0; } else { if( sum < len && cur < 0 ) return 0; for( i=cur; i>=0; --i ) { if( mark[i] || sum + num[i] > len ) continue; if( num[i+1] == num[i] && !mark[i+1] ) continue; mark[i] = 1; if( dfs( deep, i, sum+num[i] ) ) return 1; mark[i] = 0; } } return 0; } bool solve() { int i; sort( num, num+n ); if( len % 4 != 0 || num[n-1] > len/4) return 0; len /= 4; memset( mark, 0, sizeof(mark)); mark[n-1] = 1; if( dfs( 0, n-1, num[n-1] ) ) return 1; return 0; } int main() { // freopen( "c:/aaa.txt", "r", stdin ); int T; scanf( "%d", &T ); while( T-- ) { scanf( "%d", &n ); len = 0; for( int i=0; i<n; ++i ) { scanf( "%d", &num[i] ); len += num[i]; } solve() ? puts("yes") : puts("no"); } return 0; }
.