poj 2362スクウェア(簡単な深さ検索+剪定)

1927 ワード

テーマリンク:http://poj.org/problem?id=2362
タイトルの大意:
tグループの入力データがあります.各グループのデータは1行です.1行目は木の棒の本数(4<=n==20)で、木の棒の長さ(1<=stick<=10000)
正方形にするかどうかを判断します.
解析:
剪定の深さ:
剪定:1、木の棒の数は4より小さい.
    2、総棒の長さ/4=正方形の辺の長さは整数ではない.
    3、最大の棒の長さは正方形の長さより大きいです.
    4、1、2、3を除いて、3つの辺を探せばいいです.
コード:
#include <iostream>
#include <algorithm>
using namespace std;

int n ;//     
int side; //     

int cmp(int a, int b) {
	return a > b;
}

//stick       ,vis     , num       , len           
//s stick    ,       
bool dfs(int *stick, bool *vis, int num, int len, int s) {
	if(num == 3) //       ,        
		return true;
		
	for(int i=s; i<n; i++) {
		//    ,      
		if(vis[i])
			continue;
		
		vis[i] = true;
		//     side,  num  ,len = len+stick[i],        
		if(len+stick[i] < side) {
			//         ,       ,dfs()     True 
			if(dfs(stick, vis, num, len+stick[i], i))
				return true;
		}
		//     side,  num+1, len=0,s=0,            
		else if(len+stick[i] == side) {
			//         ,       ,dfs()     True 
			if(dfs(stick, vis, num+1, 0, 0))
				return true;
		}
		vis[i] = false;
	}
	
	return false;
}


int main(void) {
	int time;
	//freopen("2.in", "r", stdin);
	//freopen("2.out", "w", stdout);
	cin >> time;
	while(time--) {
		int sum = 0;
		cin >> n;
		int stick[21];
		bool vis[21];
		int maxside = 0;
		for(int i=0; i<n; i++) {
			cin >> stick[i];
			vis[i] = false;
			if(maxside < stick[i])
				maxside = stick[i];
			sum += stick[i];
		}
		
		//  1、    4 ,      ,         
		if(n<4 || sum%4 || maxside>sum/4) {
			cout << "no" << endl;
			continue;
		}
		
		sort(stick, stick+n, cmp);
		side = sum / 4;
		
		if(dfs(stick, vis, 0, 0, 0))
			cout << "yes" << endl;
		else
			cout << "no" << endl;	
	}
	
	return 0;
}