3.牛宫
(long.pas/c/cpp)
【问题描述】
AP 神牛准备给自己盖一座很华丽的宫殿。于是,他看中了一块 N*M 的矩形空地。空
地中每个格子都有自己的海拔高度。AP 想让他的宫殿的平均海拔在海平面之上(假设海平
面的高度是 0,平均数都会算吧?) 。而且,AP 希望他的宫殿尽量大,能够容纳更多的人来
膜拜他。请问 AP的宫殿最后会有多大(宫殿必须是矩形)?
【输入】
第一行为 N和 M。之后 N 行,每行 M 个数,描述的空地的海拔(取值范围在 longint
范围内)。
【输出】
输出一行,表示宫殿最大面积。
【输出输出样例】
long.in
3 2
4 0
-10 8
-2 -2
long.out
4
【数据规模】
对于 30%的数据,N,M≤50;
对于 100%的数据,N,M≤200;
他们说要用单调栈,其实我并不知道那是啥玩意儿,不过时间放宽到2s我过完了。
第一步 算前缀和,将这个矩阵压成一维。
比如样例:
4 0
-10 8
-2 -2
我就存:
4 0
-10 -2
-2 -4
比如我想让矩阵纵坐标从1开始,到二结束,于是就剩下4,-2,-4,选择那一连续的一串
使和为正且连续最长,此时可以再次使用前缀和,记录成4 2 -2,在一个一个搜1到2,1到3,2到3,
但如果这样做会使时间很慢,于是我们知道如果1到2已经是正数,那么连续最长的是2,那么就没必要搜
2到3了,因为即使为正,答案是一样的,如果存在4,就应该搜2到4。这样一个优化可以使时间变短。
还有比如此时我已经搜出最大面积为4,我们还是想让纵坐标从1开始,到二结束,此时宽度为2,而它的长度
应该超过2,就没必要搜1到2了,应该搜1到3.
说了半天应该有人头都晕了,可以用样例试一下,帮助理解。
1 #include <iostream> 2 #include <fstream> 3 #include <cstdlib> 4 #include <iomanip> 5 #include <cstring> 6 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 7 8 using namespace std; 9 ifstream fin("long.in"); 10 ofstream fout("long.out"); 11 12 int cnt_he,cnt_zo; 13 long long int jv_zhui[205][205]={0}; 14 long long int sum[205]={0}; 15 16 int xun(int z_zo,int gs,int ks){ 17 int zd=0,zd1=0; 18 long long int qianz[205]={0}; 19 for(int x=1;x<=cnt_he;x++)qianz[x]=qianz[x-1]+jv_zhui[x][ks+gs-1]-jv_zhui[x][ks-1]; 20 21 for(int x=1;x<=cnt_he;x++){ 22 long long zf=0; 23 zd1=0; 24 int fw=max(z_zo,zd); 25 if(fw==0)fw=1; 26 zf=0; 27 for(int y=x+fw-1;y<=cnt_he;y++){ 28 zf=qianz[y]-qianz[x-1]; 29 //cout<<x<<" "<<y<<" "<<ks<<" "<<gs<<" "<<zf<<endl; 30 //system ("pause"); 31 if(zf>0)zd1=y-x+1; 32 } 33 zd=max(zd1,zd); 34 } 35 //cout<<zd<<" ddd "<<endl; 36 return zd; 37 38 39 } 40 41 42 int main(int argc, char *argv[]) { 43 fin>>cnt_he>>cnt_zo; 44 for(int x=1;x<=cnt_he;x++){ 45 for(int y=1;y<=cnt_zo;y++){ 46 long long a=0; 47 fin>>a; 48 jv_zhui[x][y]=jv_zhui[x][y-1]+a; 49 } 50 } 51 52 int max_mian=0; 53 for(int x=cnt_zo;x>=1;x--){ 54 for(int y=1;y<=cnt_zo-x+1;y++){ 55 int zo=xun(max_mian/x,x,y); 56 57 max_mian=max(max_mian,x*zo); 58 } 59 } 60 cout<<max_mian; 61 fout<<max_mian; 62 63 64 return 0; 65 }
QwQ,去看了一下黄学长的题解 ,然后学了学单调栈,就过完了 。