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;
}





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