2013编程之美全国挑战赛 长方形

原题连接:http://programming2013.cstnet.cn/qualification/problem/2

题目描述:

时间限制: 1000ms 内存限制: 256MB

描述

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

输入

输入文件包含多组测试数据。

第一行,给出一个整数T,为数据组数。接下来依次给出每组测试数据。

每组数据为三个用空格隔开的整数 N,M,K。

输出

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

数据范围

1 ≤ T ≤ 100

0 ≤ K ≤ N * M

小数据:0 < N, M ≤ 30

大数据:0 < N, M ≤ 30000


样例输入
3
3 3 8
4 5 13
7 14 86
样例输出
Case #1: 5
Case #2: 18
Case #3: 1398
注:这个题目是赛后做的,只是通过了测试用例。

分析:考虑到边长为n,宽为m的长方形,可以得到C(2,m)*C(2,n)个小长方形,因此这个题目中尽量让m和n接近,最优是sqrt(k)。因此解题思路是先得到一个两边长尽可能相等的最大的长方形,再将剩余的石子放在长边的后面,如此能得到最优解。


实现代码如下:

#include <iostream>
#include <math.h>
using namespace std;

int GetRects(int m,int n);
int Solute(int n,int m,int k);

int main()
{
    int m,n,k;
    int times;

    cin >> times;
    while(times--){
        cin >> n >> m >> k;
        cout << Solute(n,m,k) << endl;
    }
    return 0;
}

int Solute(int n,int m,int k)
{
    int width,length;
    int remaind;
    int ret;

    width = floor(sqrt(k)) + 1;

    if(width > n){
        width = n;
    }
    length = k / width;
    remaind = k % width;
    if(length < width){
        int temp = length;
        length = width;
        width = temp;
    }
    length = length - 1;
    width = width - 1;

    ret = GetRects(length,width);

    if(remaind > 1){
        if(length+1==n){//note 边界因素导致不能在长边添加元素
            ret = ret + GetRects(width+1,remaind-1) - GetRects(width,remaind-1);
        }
        else{
            ret = ret + GetRects(length+1,remaind-1) - GetRects(length,remaind-1);
        }

    }
    return ret;
}
int GetRects(int m,int n)
{
    return (1+m)*m*(1+n)*n/4;
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章