【伪题解】牛宫

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,去看了一下黄学长的题解 ,然后学了学单调栈,就过完了 。

原文地址:https://www.cnblogs.com/Ateisti/p/4805506.html