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;
}
.
浙公网安备 33010602011771号