FJUT 2801 垃圾佬的正方形 深度优先搜索+剪枝

垃圾佬的正方形
TimeLimit:4000MS MemoryLimit:128MB
64-bit integer IO format:%lld
Problem Description
垃圾佬最近遇到了一个简单题。

给定一系列的棍子,问是否能把它们头尾相连组成正方形(木棍需要用完)。

由于太简单了,垃圾佬懒得去做,于是垃圾佬便把这个问题扔给了你。

Input
第一行一个正整数T,表示测试数据的组数(T<=41)。解下来每行开始于一个正整数N (4<=N<=20), 表示棍子的数目,紧接着的N个正整数字(X1,X2,X3…Xn),表示棍子的长度Xi,(1<=Xi<=10,000)。

Output
对于每组测试数据,如果可能构造成正方形,输出一个“yes”,否则输出“no”。

SampleInput
3
4 1 1 1 1
5 10 20 30 40 50
8 1 7 2 6 4 4 3 5
SampleOutput
yes
no
yes

题意:给你n个木棍问能否用全部的木棍构成一个正方形
思路:深搜+剪枝

#include <stdio.h>
#include <algorithm>
#include <string.h>

using namespace std;

int a[30];
bool vis[30];

int sum,num,n ;

bool cmp(int a,int b)
{
    return a > b;
}

bool dfs(int num,int len,int st)///已经构成边的数目  当前边的长度 添加边的起点
{
    if(num == 3)///构成三条边则另一条边已经固定直接返回成功构成
        return true;

    for(int i = st ;i < n;i ++)
    {
        if(vis[i])
            continue;

        vis[i] = true;

        if(len+a[i]<sum)///一条边还没构成继续构成改边
        {
            if(dfs(num,len+a[i],i+1))
                return true;
        }
        else if(len+a[i] == sum)///成功构成一条边
        {
            if(dfs(num+1,0,0))
                return true;
        }

        vis[i] = false;///还原该边
    }
    return false;
}

int main()
{
    int t;

    scanf("%d",&t);

    while(t--)
    {
        scanf("%d",&n);
        sum = 0;
        num = 0;

        for(int i=0; i<n; i++)
        {
            scanf("%d",&a[i]);
            sum+=a[i];
        }

        if(sum%4)///如果周长不是4的倍数直接无法构成
        {
            printf("no\n");
            continue;
        }

        sort(a,a+n,cmp);///升序排序 更长的木棍可选择的条件较少 应该优先处理

        sum/=4;

        if(a[0]>sum)///如果有最长的木棍比一条边还长也无法构成
        {
            printf("no\n");
            continue;
        }

        memset(vis,0,sizeof(vis));

        if(dfs(0,0,0))
            printf("yes\n");
        else
            printf("no\n");
    }
    return 0;
}
发布了54 篇原创文章 · 获赞 0 · 访问量 1213

猜你喜欢

转载自blog.csdn.net/weixin_44144278/article/details/102698238