在 N 条水平线与 M 条竖直线构成的网格中,放 K 枚石子
【題目描述】
在 N 條水平線與 M 條豎直線構成的網格中,放 K 枚石子,每個石子都只能放在網格的交叉點上。問在最優的擺放方式下,最多能找到多少四邊平行于坐標軸的長方形,它的四個角上都恰好放著一枚石子。
【輸入】
輸入文件包含多組測試數據。
第一行,給出一個整數T,為數據組數。接下來依次給出每組測試數據。
每組數據為三個用空格隔開的整數 N,M,K。
【輸出】
對于每組測試數據,輸出一行"Case #X: Y",其中X表示測試數據編號,Y表示最多能找到的符合條件的長方形數量。所有數據按讀入順序從1開始編號。
?
【題解】
??? 首先先考慮對于一個布滿點的矩形(x行,Y列),所有的矩形總數為 C(2,x)*C(2,y)。要使數量最多,則x和y要盡可能接近(有最大行和最大列的限制)。??? 題中所給的K可能不能剛好排成大矩形,可能有多余的幾個點,這幾個點的數量一定不會超過一行或一列的最大數量。 試想如果超過,則多出來完整的一行或一列可以和原來的大矩形構成更大的矩形,剩下的點就不能構成完整的一行或一列了。
????多余多出來的點,以一排或一列的形式,靠在大矩形短的一邊(要注意是否到達邊界),設多余K個點,則多增加的矩形數為 C(2,K)*L (L為長邊的點數)。
??? 為了簡單起見,可以規定行大于列(對調旋轉下),枚舉 X、Y的有效極大組合,找出最大的結果就行了。
??? AC代碼:
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 int n,m,k; 5 void swap(int &a,int &b) 6 { 7 int t=a; 8 a=b; 9 b=t; 10 } 11 long long getc(long long j) 12 { 13 return j*(j-1)/2; 14 } 15 int main() 16 { 17 int T; 18 scanf("%d",&T); 19 int cas=0; 20 while (T--) 21 { 22 scanf("%d%d%d",&n,&m,&k); 23 if (n<m) swap(n,m); 24 int t=sqrt(k); 25 int b=t>m?m:t; 26 int a=k/b>n?n:k/b; 27 long long max=0; 28 for (;b>=2 && a<=n;--b,a=k/b) 29 { 30 long long sum=getc(a)*getc(b); 31 int p=k-a*b; 32 if (a<n) 33 { 34 sum=sum+getc(p)*a; 35 } 36 else 37 { 38 sum=sum+getc(p)*b; 39 } 40 max=max>sum?max:sum; 41 } 42 printf("Case #%d: %I64d\n",++cas,max); 43 } 44 45 return 0; 46 }總結
以上是生活随笔為你收集整理的在 N 条水平线与 M 条竖直线构成的网格中,放 K 枚石子的全部內容,希望文章能夠幫你解決所遇到的問題。