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!");
}
}