2023.6.8每日一题

 

         经过观察和样例和数据范围,发现此题不太好找规律,数据范围小,故可以用dfs+回溯解决

确定返回条件:

        1.如果当前的使用的地砖数大于存的最小答案,就可以回溯,不再向下搜

        2.如果没在1处返回并且当前铺的面积已经等于总面积n*m,便记录答案,返回

搜索:

        先确定当前正方形的起点,循环枚举他的最大边长(边长不超过任一总长且此正方形所在位置还未被覆盖)。

        循环中,如果满足刚才的条件,就把正方形所在位置填1,并找到下一个还未被填的起点继续dfs。

        在回溯中,只需要将上一步填过1的地方填0释放即可。

class Solution {
public:

    bool vis[15][15]; 
    int ans;
    int x2,y2;

    int tilingRectangle(int n, int m) {
	    ans=n*m;
	    memset(vis,false,sizeof(vis));	
	    dfs(0,0,0,0,n,m);
	    return ans;
    }

void fill(int x1,int y1,int i1,bool sta) //填值
{
	for(int i=x1;i<x1+i1;i++)
	{
		for(int j=y1;j<y1+i1;j++)
		{
			vis[i][j]=sta;
		}
	}
}

void find(int n,int m)  //找到下一个还未填1的位置
{
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(vis[i][j]==false)
			{
				x2=i;
				y2=j;
				return ;
			}
		}
	}
}

bool check(int x1,int y1,int i1) //检查当前正方形是否能填
{
	for(int i=x1;i<x1+i1;i++)
	{
		for(int j=y1;j<y1+i1;j++)
		{
			if(vis[i][j]==true) return 0;
		}
	}
	return 1;
}


void dfs(int x,int y,int s,int cur,int n,int m)
{
	if(cur>=ans) return; //剪枝
	if(s==n*m)  //满足条件
	{
		ans=cur;
		return;
	}
	
	for(int i=min(n-x,m-y);i>0&&check(x,y,i);i--)  //枚举所在起点的边长
	{
		fill(x,y,i,true); //填1
		find(n,m); //找到下一个还未填的位置
		dfs(x2,y2,s+i*i,cur+1,n,m); //dfs
		fill(x,y,i,false); //回溯,填0
	}
}

};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值