poj stick


#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
int stick[205];
bool visit[205];
int n, m, sum;
bool bfs(int fran, int side, int sl)//fran表示可以选择的木棍的范围,木根默认排序,sl表示当前这条边已经组成的长度
{
	if (side == 3)
		return true;
	else
	{
		for (int i = fran; i >= 0; i--)
		{
			if (!visit[i])
			{
				visit[i] = true;//避免递归进行访问时重复访问
				if (stick[i] + sl < sum)
				{
					if (bfs(i - 1, side, stick[i] + sl))
						return true;
				}
				if (stick[i] + sl == sum)
				{
					if (bfs(m - 1, side + 1, 0))//当前边长清零
						return true;
				}
				visit[i] = false;
			}
		}
	}
	return false;
}
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		cin >> m;
		memset(stick, 0, sizeof(stick));
		memset(visit, 0, sizeof(visit));
		sum = 0;
		int max = -1;
		for (int i = 0; i < m; i++)
		{
			cin >> stick[i];
			sum += stick[i];//求相应木棍长度的总和
			if (stick[i] > max)max = stick[i];
		}
		if (max > sum / 4||m<4||sum%4!=0)
			cout << "no" << endl;
		else
		{
			sort(stick, stick + m);//将木棍长度进行排序,木棍越短灵活度越高
			sum = sum / 4;//计算边长
			if (bfs(m - 1, 0, 0))
			{
				cout << "yes" << endl;
			}
			else
			{
				cout << "no" << endl;
			}
		}
	}
	getchar();
	getchar();
	return 0;
}


1、本题关键在于理解剪枝的过程,判断是否能够构成正方形,有三种过程可以剪枝,1、若木棍的总数小于4,  2、木棍长度的总和是否可以整除4    3、最大木棍的长度是否大于边长
2、本题中要求的是将所有的木棍使用完全,因为木棍长度越小,活动性越高,所以访问木棍长度时,先进行排序,当满足可以组成三条边时,第四条边可自动满足

3、递归函数的设置,引入一个变量记录组成当前这条边已有的长度,若满足边长,则将该变量清空,继续记录下一条边寻找过程,若不满足,则继续进行寻找,知道满足边长要求为止
4、关键注意理解利用木棍长度匹配边长的过程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值