poj 2362 Square(简单深搜+剪枝)

15 篇文章 0 订阅
10 篇文章 0 订阅

题目链接:http://poj.org/problem?id=2362


题目大意:

有t组输入数据,每组数据一行;每行第一个为木棍根数(4<=n<=20),每根木棍长度(1<=stick<=10000)

判断能否拼成一个正方形


解析:

深搜剪枝:

剪枝:1、木棍数目小于4

    2、总木棍长度/4=正方形边长不为整数

    3、最大的木棍长度大于正方形边的长度

    4、除1、2、3外,找到三条边即可

Code:

#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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值