微软编程之美 Qual_B:长方形 思维

探讨在有限网格中放置石子以形成最多矩形的问题。通过填充正方形及补充剩余石子来最大化矩形数量,采用枚举行数策略寻找最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接



题意:

在 N 条水平线与 M 条竖直线构成的网格中,放 K 枚石子,每个石子都只能放在网格的交叉点上。问在最优的摆放方式下,

最多能找到多少四边平行于坐标轴的长方形,它的四个角上都恰好放着一枚石子。



思路:


这个题想了好多,还是没想明白。这就比较菜了...

     这个题的话,先考虑什么情况下会使得得到的长方形最多.肯定是将其尽可能的填成x*y的形状的.即:x*y的格子中每一点都存在石子.从而可以得到C(x,2)*C(y,2)个长方形,.那么我们先考虑填成一个正方形,在继续补.k个石子最多可以填成kk=sqrt(k) ,kk*kk的正方形(超过就重复了),那么剩下的石子我们先考虑,将他补到长边上,这样新增加的和长边的又能构成很多的长方形,设剩余的为L ,即为C(L,2)*x(长边长).如果长边长超过了最大的限制,再补到短边上.

     对于给定的k一定存在行列关系使得其最大,这里我们就枚举一个行的关系,固定行的大小小于列.并维护最优解

#include<bits/stdc++.h>
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define inf 0x3f3f3f3f
#define exp 0.00000001
#define  pii  pair<int, int>
#define  mp   make_pair
#define  pb   push_back
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int n,m,k;
int t;
ll C(int s)
{
	return s*(s-1)/2;
}
ll solve(int x,int y)
{
	if(y<m)
	return C(x)*C(y)+y*C(k-x*y);
	else
	return C(x)*C(y)+x*C(k-x*y);
}
int main()
{
	Ri(t);
	int tt=1;
	W(t)
	{
		Ri(n),Ri(m),Ri(k);
		if(n>m)
		swap(n,m);
		int kk=sqrt(k);
		int w=min(kk,n);
		ll ans=0;
		for(int i=2;i<=w;i++)
		{
			kk=min(m,k/i);
			if(k>=kk*(i+1))//必须要保证多余石子少于边长
			continue;
			ll ss=solve(i,kk);
			ans=max(ss,ans);
		}
		printf("Case #%d: ",tt++);
		Pl(ans);
	}
 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Marcus-Bao

万水千山总是情,只给五角行不行

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

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

打赏作者

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

抵扣说明:

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

余额充值