PROGRAMMING GRIDS 木棍正方形

前面用迭代不知道为什么出错,后来改用递归

算法思想:

首先若木棒长度和不是4的整数倍则不可能构成正方形,逐条边填充,如遇到一条边不能填充则CUT

考虑几种分支情况:

如果当前边剩余空间为0

若剩余木棒也为0,则已经填充完毕(此时一定恰好填充了4条边)

否则填充下一条边

对每条边设立使用标记,从未使用的第一条边开始逐个填入,填入时将访问标记设为true(之后归还),递归填其余边

如果剩余木棒可以填充在剩余空间中,则直接返回TRUE

如果不能填充,取消当前木棒,若当前木棒已经填满某条边,则其余木棒不用再填充(取掉之后也一样)

如果下一条木棒和当前木棒相同,则也不用比较

代码:

# include <iostream>
# include <vector>
# include <algorithm>
# include <queue>

using namespace std;

int EdgeLength = 0;
vector<int> stickStorage;
vector<bool> usage;

bool pathFinder(int stickRemain, int spaceRemain, int subscription)
{
	int spcR = spaceRemain;
	int stkR = stickRemain;
	if ( spaceRemain == 0 )
	{
		if ( stickRemain == 0 )
		{
			return true;
		}
		spcR = EdgeLength;
		subscription = 0;
	}
	int size = stickStorage.size();
	for ( int i = subscription ; i < size; i++ )
	{
		if ( usage[i] == false && stickStorage[i] <= spcR )
		{
			usage[i] = true;
			if ( pathFinder(stkR-1,spcR-stickStorage[i],i+1) )
			{
				return true;
			}
			usage[i] = false;
			if ( stickStorage[i] == spcR || spcR == EdgeLength )	//If the current stick fills a line, there's no need to compare any more
			{
				break;
			}
			while ( stickStorage[i] == stickStorage[i+1] && i < size-1 )
			{
				i++;
			}
		}
	}
	return false;
}

int main()
{
	int n = 0;
	int stickNum = 0;
	int currentStickLen = 0;
	bool possible = false;
	int sum = 0;
	
	cin >> n;

	int j = 0;
	for ( int i = 0; i < n; i++ )
	{
		possible = false;
		EdgeLength = 0;
		sum = 0;
		stickStorage.clear();
		usage.clear();
		cin >> stickNum;
		for ( j = 0; j < stickNum; j++ )
		{
			cin >> currentStickLen;
			sum += currentStickLen;
			stickStorage.push_back(currentStickLen);
			usage.push_back(false);
		}
		sort(stickStorage.begin(),stickStorage.end(),greater<int>());
		if ( sum%4 != 0 )
		{
			possible = false;
		}
		else
		{
			EdgeLength = sum/4;
			possible = pathFinder(stickStorage.size(),EdgeLength,0);
		}
		if ( possible )
		{
			cout << "yes" << endl;
		}
		else 
		{
			cout << "no" << endl;
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值