2013编程之美资格赛【长方形】

题目:在 N 条水平线与 M 条竖直线构成的网格中,放 K 枚石子,每个石子都只能放在网格的交叉点上。问在最优的摆放方式下,最多能找到多少四边平行于坐标轴的长方形,它的四个角上都恰好放着一枚石子。

输入:输入文件包含多组测试数据。第一行,给出一个整数T,为数据组数。接下来依次给出每组测试数据。每组数据为三个用空格隔开的整数 N,M,K。

输出:对于每组测试数据,输出一行"Case #X: Y",其中X表示测试数据编号,Y表示最多能找到的符合条件的长方形数量。所有数据按读入顺序从1开始编号。

样例输入

3
3 3 8
4 5 13
7 14 86
样例输出
Case #1: 5
Case #2: 18
Case #3: 1398
刚开始看着题目的时候,没有想法,就单单AC了传话游戏那题;今天在网上看了看别人的思路,发觉其实类似于上周微软笔试那道3*4矩阵中有多少个矩形的题目,恍然大悟;
思路: 转自http://www.cnblogs.com/wuminye/archive/2013/04/07/3006425.html   
    首先先考虑对于一个布满点的矩形(x行,Y列),所有的矩形总数为 C(2,x)*C(2,y)。要使数量最多,则x和y要尽可能接近(有最大行和最大列的限制)。题中所给的K可能不能刚好排成大矩形,可能有多余的几个点,这几个点的数量一定不会超过一行或一列的最大数量。 试想如果超过,则多出来完整的一行或一列可以和原来的大矩形构成更大的矩形,剩下的点就不能构成完整的一行或一列了。
    多余多出来的点,以一排或一列的形式,靠在大矩形短的一边(要注意是否到达边界),设多余K个点,则多增加的矩形数为 C(2,K)*L (L为长边的点数)。
上代码:没有提交过,不晓得对错,自己测试了几组数据是对的;
#include <iostream>
#include <cmath>
using namespace std;

int getNRec(int x)
{
	if(x == 1)
		return 1;
	return x*(x+1)/2;
}

void main()
{
	int cnt;
	int temp, i, j, remain, res = 0;
	int m, n, k, pq = 0;
	int width, length;
	cin >>cnt;
	for(i = 0; i < cnt; i++)
	{
		res = 0;
		cin >>n>>m>>k;
		temp = sqrt(k);
		if(n < m)
		{
			j = m;m = n;n = j;
		}
		width = temp>m?m:temp;
		length = (k/width)>n?n:(k/width);
		remain = k - width*length;
		res = getNRec(width-1)*getNRec(length-1);
		
		cout <<"Case #"<<++pq<<": ";
	
		if(remain >= 2)
		{
			if(length == n)
			{
		res += getNRec(remain-1)*getNRec(width) - getNRec(remain-1)*getNRec(width-1);
			}
			else
			{
		res += getNRec(remain-1)*getNRec(length) - getNRec(remain-1)*getNRec(length-1);
			}
		}
		cout <<res<<endl;
		
	}
}

看看有没有热心网友大牛,分析下对不对啊~~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值