HDU1518 Square

                                                         Square

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5710    Accepted Submission(s): 1812


Problem Description
Given a set of sticks of various lengths, is it possible to join them end-to-end to form a square?
 

Input
The first line of input contains N, the number of test cases. Each test case begins with an integer 4 <= M <= 20, the number of sticks. M integers follow; each gives the length of a stick - an integer between 1 and 10,000.
 

Output
For each case, output a line containing "yes" if is is possible to form a square; otherwise output "no".
 

Sample Input
  
  
3 4 1 1 1 1 5 10 20 30 40 50 8 1 7 2 6 4 4 3 5
 

Sample Output
  
  
yes no yes
 

Source
 

Recommend
LL


解题思路:本题为深度优先搜索典型题目,重点在于看懂题目,化整为零逐个击破。我开始以为题目的意思是说,在给出的棍子里面随便拿一些出来拼接,只要能拼成正方形即可。郁闷了很久,事实证明,我理解错了。题目的意思是,所有的棍子都得用上,问能不能拼出正方形。这样,就简单多了,就只要四次拼出总长度的4分之一久可以了,还可以根据总长能否整分和最长的棍子与平均值长度的关系直接剪枝。


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,a[20],flag[20];
int max_len,avr;
int f;
void dfs(int start,int count,int len)
{
    if(len>avr||f)
        return ;
    if(len==avr)    //一条边拼接完成
    {
        count++;
        if(count==4)     //四条边拼接完成
        {
            f=1;
            return ;
        }
        len=0;
        start=0;
    }
    if(f)
        return ;
    for(int i=start;i<n;i++)
    {
        if(!flag[i])
        {
            flag[i]=1;
            dfs(i,count,len+a[i]);
            flag[i]=0;
        }
    }
}
int main()
{
    int t;
    int i;
    scanf("%d",&t);
    while(t--)
    {
        f=0;
        max_len=0;
        int sum=0;
        memset(flag,0,sizeof(flag));
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            sum+=a[i];
            max_len=max(a[i],max_len);
        }
        if(sum%4!=0||max_len>sum/4);     // 总数不能整分或最大值大于平均值,皆不能拼成正方形
        else
        {
            avr=sum/4;
            dfs(0,0,0);
        }
        if(f)
            printf("yes\n");
        else
            printf("no\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值