您的位置:首页 > 编程语言 > C语言/C++

【DFS+剪枝】-HDU-1518-Squares

2014-02-18 18:28 246 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1518

题目描述:给出若干个破木头条子。问你它们能否拼成一个正方形。

解题思路:

一道DFS题,DFS是我软肋啊。不过经过这道题,算是找到一种固定模式了,以后遇到DFS题就不会不知♂所措。

解释一下我DFS函数中的变量 len 和 dep,分别表示手里拿的木棍总长,每当达到一个边长就放下这些木棍(并标记),再从头开始找,dep表示已找到的边长数量,显然找到 4 个就能构成正方形。

交上去T了。

所以我们再考虑剪枝,问题出在我写的基本上是一个生成全排列的DFS,而这道题显然不用考虑顺序,所以每次不用从 1 开始搜,加入一个 from 变量记一下位置,下次接着搜就好了,也就是说 “排列” 和 “组合” 是不同的。这样就AC了。

我还在想,那是不是不需要 use 数组了,去掉是 WA 的,因为在你凑齐一个边长并放下手里木棍时候必须标记好用过哪些,再找的时候才是对的。

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

int arr[30],use[30];
int num,sum,found;

void dfs(int from,int len,int dep)
{
if(!found&&len<=sum/4)
{
//cout<<len<<" "<<dep<<endl;
int i;
if(len==sum/4)
{
if(dep==4)
found=1;
else
dfs(1,0,dep+1);
}
else
{
for(i=from;i<=num;i++)
{
if(!use[i])
{
use[i]=1;
dfs(i+1,len+arr[i],dep);
use[i]=0;
}
}
}
}
}

int main()
{
//freopen("1518_input.txt","r",stdin);
int T,i;
scanf("%d",&T);
while(T--)
{
scanf("%d",&num);
sum=0;found=0;
memset(arr,0,sizeof(arr));
memset(use,0,sizeof(use));
for(i=1;i<=num;i++)
{
scanf("%d",&arr[i]);
sum+=arr[i];
}
if(sum%4!=0)
{
printf("no\n");
}
else
{
dfs(1,0,1);
if(found)
printf("yes\n");
else
printf("no\n");
}
}

return 0;
}
AC截图:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息