HDU1518_dfs拼正方形

1.题目链接。题目的意思十分简单,就是给你一些木棒以及这些木棒的长度,问他们能不能拼成一个正方形。看到这个问题,我们首先想到的是这些木棒的总和一定要是4的倍数,否则一定是不可行的。但是就算是判断了是4的倍数,之后该怎么办呢?我们可以采用dfs搜索解决这个问题。dfs的参数:cur,pos,res.我们首先明确一个问题,如果这些数据满足条件,我们拼完3条边就行了,最后一条边一定是成立的。所以我们dfs就是对每一条边dfs,我们搜索的目的就是为了拼好每一条边。cur就是代表了拼好了多少条边,pos代表现在在用那一个木棒,res是什么呢?我们直到每一条边的长度是周长的4分之一,我们dfs的目的就是拼好每一条边。所以res代表的就是我们当前正在拼的这一条边还需要多少。dfs很重要的就是关于递归出口的确定,我们刚才已经说了,cur=3即可结束。那么剩下的状态如何转移?假设我们现在面临的木棒的长度是s,如果res=s,那么把这个木棒加入到cur这条边,cur+1,pos=0,res=goal.进行下一条边的操作。如果s<res,那么这条边依然加进来,但是cur不变,pos+1.res-s.继续进行下一轮搜索。分析好了这些,代码一经写完了。代码如下,不懂得再模拟一下就明白了。AC了之后看其他大佬的代码,发现他们都有对长度排序,我不是很理解为什么要排序,可能是因为想在遍历的时候尽快的找到符合的长度。

#include"stdafx.h"
#include<iostream>
#include<cstring>
#include<algorithm>
#pragma warning(disable:4996)
using namespace std;
const int N = 25;
int a[N];
int used[N];
int goal = 0;
int t;
bool cmp(int a, int b)
{
	return a > b;
}
bool  dfs(int cur, int pos, int res)
{
	if (cur == 3)
	{
		return true;
	}
	for (int i = pos; i < t; i++)
	{
		if (used[i])continue;
		used[i] = 1;
		if (a[i] == res)
		{
			if (dfs(cur + 1, 0, goal))
			{
				return true;
			}
		}
		if (a[i] < res)
		{
			if (dfs(cur, i + 1, res - a[i]))
			{
				return true;
			}
		}
		used[i] = 0;
	}
	return false;
}
int main()
{
	int T;
	scanf("%d", &T);
	int sum=0;
	while (T--)
	{
		int sum = 0;
		scanf("%d", &t);
		for (int i = 0; i < t; i++)
		{
			scanf("%d", &a[i]);
			sum += a[i];
		}
		if (sum % 4 != 0)
		{
			puts("no");
			continue;
		}
		goal = sum / 4;
		memset(used, 0, sizeof(used));
		if (dfs(0, 0, goal))
		{
			puts("yes");
		}
		else
		{
			puts("no");
		}

	}
}

猜你喜欢

转载自blog.csdn.net/weixin_41863129/article/details/85876772