贪心算法 | 473火柴拼正方形 怎么用C++实现摆放火柴棍?

17 篇文章 0 订阅
12 篇文章 0 订阅
文章介绍了如何使用递归函数解决一个问题,即给定一定数量的火柴棍,判断是否能用它们摆成一个正方形。首先,通过遍历火柴棍并尝试放入四个边中,同时维护每条边的火柴棍总数。如果所有边的火柴棍数相等且等于总火柴棍数的一半,表示可以组成正方形。代码示例使用C++实现,并包含排序和回溯操作以优化解决方案。
摘要由CSDN通过智能技术生成

题目

        已知一个数组,保存了n个(n<=15)火柴棍,问可否使用这n个火柴棍摆成一个正方形?

        例如:[1,1,2,2,2] --true  2  

求解

思路

  • num[i] :第i条火柴棍
  • bucket[j]:每j条边上的火柴棍长度
  • sum:每条边要求的火柴棍总长度,题目中的sum=2

        思路为依次访问火柴棍,判断可以放在第j条边内不(能否放置取决于放置后的bucket[j]是否大于sum),可以就放,然后递归的走下一根火柴棍,不可以就j++访问下一条边

        递归结束条件:

  • i>=num.size(),访问到最后一根火柴棍

代码实现

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>

bool fn(int i,vector<int>&num,int sum,int bucket[])
{
	if (i >= num.size())//此时说明火柴棍放完啦
	{
		//看4条边是否等于sum
		return bucket[0] == sum && bucket[1] == sum && bucket[2] == sum &&
			bucket[3] == sum;
	}
	//去放置4条边
	for (int j = 0; j < 4; j++)//每次递归的时候j都=0,从第一条边开始
	{
		if (bucket[j] + num[i] > sum)
			continue;
		bucket[j] = bucket[j] + num[i];
		if (fn(i + 1, num, sum, bucket))//递归完毕,执行该语句返回ture
			return true;
		bucket[j] -= num[i];//回溯
	}
	return false;
}

void main()
{
	int num[] = { 1,1,2,2,2 };//测试用例
	vector<int> vv(num, num + 5);
	int bucket[4] = { 0 }; //4条边
	sort(vv.begin(), vv.end(),greater<int>());//从大到小排序,优化代码执行效率
	int s = 0;
	for (int i = 0; i < 5; i++)
		s = s + num[i];
	if (s % 4 != 0)
	{
		cout << "不能" << endl;
		return;
	}
	if (vv.size() < 4)
	{
		cout << "不能" << endl;
		return;
	}

	if (fn(0, vv, s / 4, bucket))
		cout << "能组成" << endl;
	else
		cout << "不能组成" << endl;

}

力扣

代码

class Solution {
public:
    bool fun(int i,vector<int>& matchsticks, int bucket[],int sum)
    {
        if(i>=matchsticks.size())
        {
            return bucket[0]==sum&&bucket[1]==sum&&bucket[2]==sum&&bucket[3]==sum;
        }
        for(int j=0;j<4;j++)
        {
            
            if(bucket[j]+matchsticks[i]>sum)
            {
                //fun(i+1,matchsticks,bucket,sum);
                continue;
            }
            else
            {
                bucket[j]+=matchsticks[i];
                // fun(i+1,matchsticks,bucket,sum);
                if(fun(i+1,matchsticks,bucket,sum))
                {
                   return true;
                }
                bucket[j]-=matchsticks[i];
                //return false;
           }
        }
        return false;

    }
    bool makesquare(vector<int>& matchsticks){//,int bucket[]) {
        int sum=0;
        int bucket[4]={0};
        int i;
        /*for(i=0;i<matchsticks.size(),i++)
        {
            sum+=matchsticks[i];
        }*/
        sum=accumulate(matchsticks.begin(),matchsticks.end(),0);//初值为0
        sort(matchsticks.begin(),matchsticks.end(),greater<int>());//一定要优化不然时间通不过
        if(sum%4!=0)
            return false;
        sum=sum/4;
        if(fun(0,matchsticks,bucket,sum))
        {
            return true;
        }
        return false;
    }
};

运行结果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值