dfs拼木棒,剪枝

hdoj 1455 Sticks

这题对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;
}

.

posted on 2011-03-14 22:04  CrazyAC  阅读(327)  评论(0编辑  收藏  举报