原題連接: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;
}