POJ 2362 Square (搜索 + 剪枝)

poj 2362


发现了两个可以剪枝的地方,不过看大神的博客说还有更多可以剪枝的地方,能到十多毫秒,给跪了。

我能写成这样已经很满足了,在剪枝之前,还是要先把深搜练熟练。祥见代码。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int M, b, flag;
int stick[30], book[30];
bool cmp(int a, int b) {
	return a > b;
}
void dfs(int len, int num, int start) {
	if(len == 0) {
		if(num == 0) {
			flag = 1;
		}
		else dfs(b, num - 1, 0);
	}
	else {
		int i;
		for(i = start; i < M && !flag; i++) {	//flag = 1表示已经找到,也算是一个小优化吧 
			if(!book[i] && stick[i] <= len) {	//此根棍一定不能比剩余的长度长。 
				book[i] = 1;
				dfs(len - stick[i], num, i + 1);
				book[i] = 0;
			}
		}
	}
}
int main () {
	//freopen("input.txt", "r", stdin);
	int N;
	scanf("%d", &N);
	while(N--) {
		flag = 0;
		scanf("%d", &M);
		int i, sum = 0;
		for(i = 0; i < M; i++) {
			scanf("%d", stick + i);
			sum += stick[i];
			book[i] = 0;
		}
		if(M < 4 || sum % 4 != 0) {		//显然不能组成正方形 
			printf("no\n");
			continue;
		}
		b = sum >> 2;		//b为正方形的边长。 
		sort(stick, stick + M, cmp);	//降序排序后能组成前三条边的种数就少了,可以少量优化时间 
		if(b < stick[0]) {		//最长棍不能大于正方形边长 
			printf("no\n");
			continue;
		}
		dfs(b, 3, 0);		//由于是正方形,只需要搜出三条边就足够了 
		printf(flag ? "yes\n" : "no\n");
	}
	return 0;
}


你可能感兴趣的:(POJ 2362 Square (搜索 + 剪枝))