dp--悬线dp P4147 玉蟾宫
题目背景
有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地。
题目描述
这片土地被分成$N\times M$个格子,每个格子里写着'$R$'或者'$F$',$R$代表这块土地被赐予了$rainbow$,F代表这块土地被赐予了$freda$。
现在$freda$要在这里卖萌。。。它要找一块矩形土地,要求这片土地都标着'$F$'并且面积最大。
但是$rainbow$和$freda$的$OI$水平都弱爆了,找不出这块土地,而蓝兔也想看freda卖萌(她显然是不会编程的……),所以它们决定,如果你找到的土地面积为$S$,它们每人给你S两银子。
输入格式
第一行两个整数$N$,$M$,表示矩形土地有$N$行$M$列。
接下来$N$行,每行$M$个用空格隔开的字符'$F$'或'$R$',描述了矩形土地。
输出格式
输出一个整数,表示你能得到多少银子,即(43\times$最大'$F$'矩形土地面积)的值。
大体思路就是一共三个数组,表示三个方向:$r[i][j]$表示当前位置能向右拓展的最远位置,$l[i][j]$表示当前位置能向左拓展的最远位置,$up[i][j]$表示当前位置能向上拓展的最远位置。由于“木桶效应”,我们所能围城的最大矩形的面积其实也取决于最短的一个长度,$r-l+1$就是矩形的长,$i-up$就是矩形的高,长和高都知道了的话,矩形的面积就很好求了吧,说的可能比较简略。
代码如下:
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 int n,m; 5 int a[2000][2000]; 6 char c; 7 int l[2000][2000]; 8 int r[2000][2000]; 9 int up[2000][2000]; 10 int main() 11 { 12 scanf ("%d%d",&n,&m); 13 for (int i = 1;i <= n;i++) 14 { 15 for (int j =1;j<= m;j++) 16 { 17 cin>>c; 18 if (c=='F') 19 a[i][j]=1; 20 l[i][j]=j; 21 r[i][j]=j; 22 up[i][j]=i; 23 } 24 } 25 for (int i = 1;i <= n;i++) 26 { 27 for (int j = 2;j <= m;j++) 28 { 29 if (!a[i][j]^a[i][j-1]&&a[i][j]==1) 30 l[i][j]=l[i][j-1]; 31 } 32 } 33 for (int i = 1;i <= n;i++) 34 { 35 for (int j = m-1;j >= 1;j--) 36 { 37 if (!a[i][j]^a[i][j+1]&&a[i][j]==1) 38 r[i][j]=r[i][j+1]; 39 } 40 } 41 for (int i = 2;i <= n;i++) 42 { 43 for (int j = 1;j <= m;j++) 44 { 45 46 if (!a[i-1][j]^a[i][j]&&a[i][j]==1) 47 up[i][j]=up[i-1][j],l[i][j]=max(l[i-1][j],l[i][j]),r[i][j]=min(r[i-1][j],r[i][j]); 48 } 49 } 50 int ans=0; 51 int tmp; 52 for (int i = 1;i <= n;i++) 53 { 54 for (int j = 1;j <= m;j++) 55 { 56 if (a[i][j]==1) 57 { 58 tmp = r[i][j]-l[i][j]+1; 59 ans=max(ans,tmp*(i-up[i][j]+1)); 60 } 61 } 62 } 63 cout<<ans*3<<endl; 64 return 0; 65 }