HDU1518 DFS

传送门

题意就是好多棍子,看能不能拼成正方形。主要注意的有几点:
  • 所有棍子都要用到,不能剩余
  • 输入已经保证大于4根棍子了。所以无需判断可能小于3根棍子的情况
  • 棍长的总数首先要是4的倍数,才能进行。否则直接输出 “no”
  • 当前面前提满足以后,再满足3 根棍子拼好,就完工了。最后一根一定能拼好。
解法就是DFS------->深度优先搜索。DFS的思路就是一个图沿着一条路走下去,当走不下去的时候就回溯到上一结点再去走没有走过的岔路。
换算成数据结构的话,就要有一个“标记”来标记每个结点是否走过。DFS具体的实现方式,常见的一种就是: 循环里面嵌套 递归,这也算是一个DFS的框架。而剩下的要补充的“题眼”(也就是关键的地方)是要转移的 状态
bool dfs(int count,int pos,int res)
这是本题中DFS算法的状态。三个要素 count (已经拼好的棍子个数),pos (现在遍历的第几根棍子),res (要凑成目标长度剩余的长度)
当然在输入数据以后要进行一次排序,从大到小排好依次遍历。
我们要定义一个全局的变量 goal 代表你要凑齐的目标长度,换句话说就是总长度的 1/4 。
goal = sum/4;
标记的数组我们定义为used[21].值为 true 则标记过,即用过了。值为 false 则未用过。
//声明,全局
bool used[21];
//初始化为false,main函数中
memset(used,false,sizeof(used));
下面看DFS函数的代码:
bool dfs(int count,int pos,int res)
{
	if(count==3)//3根拼好就能保证都拼好
		return true;
	for(int i=pos;i<t;i++)//DFS框架循环
	{
		if(used[i])//1
			continue;
		used[i] = true;//2
		if(stick[i]==res)//3
		{//DFS框架中的递归

			if(dfs(count+1,0,goal))//4
				return true;
		}
		else if(stick[i]<res)//5
		{//DFS框架中的递归
			if(dfs(count,i+1,res-stick[i]))//6
				return true;
		}
		used[i] = false;//7
	}
	return false;
}
//1:如果标记过就跳过下面过程
//2:先标记好true
//3:如果第i根棍子的长度和你剩余的所需要的棍子的长度一样。那么这根棍子就拼好了
//4:由//3可知,又拼好了一根,所以递归下一个棍子要拼的状态,count+1。而pos初始化为0.从头开始便利,res变为goal,即下一根棍子剩余的长度是全部所需长度。
//5:如果第i根棍子的长度小于目前所需的。那么也把它加上
//6:下一个状态。count不变,因为这根还没拼好。pos = i+1,因为第i根已用。res-stick[i] 不言而喻了。
//7:前面如果满足的话,就会返回true。而不执行这一句//7这句。如果能走到//7这句,那么就是说前面的情况都不成功,也就是说这根棍子不能凑近去,所以要推翻加入这根棍子的方案

完整代码:
#include <iostream>
#include <algorithm>
using namespace std;
bool used[21];
int stick[21];
int t,goal;
bool cmp(int a,int b)
{
	return a>b;
}
bool dfs(int count,int pos,int res)
{
	if(count==3)//3根拼好就能保证都拼好
		return true;
	for(int i=pos;i<t;i++)//DFS框架循环
	{
		if(used[i])
			continue;
		used[i] = true;
		if(stick[i]==res)
		{
			if(dfs(count+1,0,goal))//DFS框架中的递归
				return true;
		}
		else if(stick[i]<res)
		{
			if(dfs(count,i+1,res-stick[i]))//DFS框架中的递归
				return true;
		}
		used[i] = false;
	}
	return false;
}
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		cin>>t;
		int sum=0;
		for(int i=0;i<t;i++)
		{
			cin>>stick[i];
			sum+=stick[i];
		}
		if(sum%4)
		{
			printf("no\n");
			continue;
		}
		goal = sum/4;
		memset(used,false,sizeof(used));
		sort(stick,stick+t,cmp);
		if(dfs(0,0,goal))//初始态
			printf("yes\n");
		else
			printf("no\n");
	}
	return 0;
}

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

果冻虾仁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值