leetcode 火柴拼正方形

473. 火柴拼正方形

题目链接:https://leetcode-cn.com/problems/matchsticks-to-square/

题目:

还记得童话《卖火柴的小女孩》吗?现在,你知道小女孩有多少根火柴,请找出一种能使用所有火柴拼成一个正方形的方法。不能折断火柴,可以把火柴连接起来,并且每根火柴都要用到。

输入为小女孩拥有火柴的数目,每根火柴用其长度表示。输出即为是否能用所有的火柴拼成正方形。

示例 1:

输入: [1,1,2,2,2]
输出: true

解释: 能拼成一个边长为2的正方形,每边两根火柴。

示例 2:

输入: [3,3,3,3,4]
输出: false

解释: 不能用所有火柴拼成一个正方形。

注意:

  • 给定的火柴长度和在 0 到 10^9之间。
  • 火柴数组的长度不超过15。

解题思路:

题意很清晰,就是把输入的数组分成四个长度相等的子数组。
是一道很经典的回溯的题目。
既然是回溯必然少不了dfs(深度优先搜索)

leetcode AC代码

class Solution {
public:
    bool makesquare(vector<int>& nums) {
        int sum=0;
        int len=nums.size();
        for(auto u:nums)sum+=u;
        if(!sum||sum%4!=0)return false;
        sum/=4;
        vector<bool> used = vector<bool>(len);
        return dfs(nums,used,sum,len,4,0,0);
    }

    bool dfs(vector<int>& nums,vector<bool>& used,int sum,int len,int k,int start,int tot)
    {
        if(k==0)return true;
        if(tot==sum)
        return dfs(nums,used,sum,len,k-1,0,0);
        for(int i=start;i<len;i++)
        {
            if(!used[i])
            {
                if(tot+nums[i]<=sum)
                {
                    used[i]=true;
                    if(dfs(nums,used,sum,len,k,i+1,tot+nums[i]))
                    return true;
                    used[i]=false;
                }
            }
        }
        return false;
    }
};

C++常规代码

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
typedef long long ll;
typedef pair<int,int>pi;

const int maxn=1e5+100;
const int N=1e5+100;
const int M=1e5+100;
const int mod=1e9+7;

int n;
int len[N];
bool used[N];
int sum=0;

bool dfs(int k,int start,int tot)
{
    if(k==0)return true;
    if(tot==sum)
    {
        return dfs(k-1,0,0);
    }
    for(int i=start; i<n; i++)
    {
        if(!used[i])
        {
            if(tot+used[i]<=sum)
            {
                used[i]=true;
                if(dfs(k,i+1,tot+len[i]))
                    return true;
                used[i]=false; //回溯
            }
        }
    }
    return false;
}

int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
#endif
    scanf("%d",&n);
    for(int i=0; i<n; i++)
        scanf("%d",&len[i]);
    for(int i=0; i<n; i++)
        sum+=len[i];
    if(!sum||sum%4!=0)
        puts("No!");
    else
    {
        sum/=4;
        if(dfs(4,0,0))
            puts("Yes!");
        else
            puts("No!");
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

__Wedream__

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

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

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

打赏作者

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

抵扣说明:

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

余额充值