洛谷1736创意吃鱼法

题目背景

感谢@throusea 贡献的两组数据

题目描述

回到家中的猫猫把三桶鱼全部转移到了她那长方形大池子中,然后开始思考:到底要以何种方法吃鱼呢(猫猫就是这么可爱,吃鱼也要想好吃法 ^_*)。她发现,把大池子视为01矩阵(0表示对应位置无鱼,1表示对应位置有鱼)有助于决定吃鱼策略。

在代表池子的01矩阵中,有很多的正方形子矩阵,如果某个正方形子矩阵的某条对角线上都有鱼,且此正方形子矩阵的其他地方无鱼,猫猫就可以从这个正方形子矩阵“对角线的一端”下口,只一吸,就能把对角线上的那一队鲜鱼吸入口中。

猫猫是个贪婪的家伙,所以她想一口吃掉尽量多的鱼。请你帮猫猫计算一下,她一口下去,最多可以吃掉多少条鱼?

输入输出格式

输入格式:

 

有多组输入数据,每组数据:

第一行有两个整数n和m(n,m≥1),描述池塘规模。接下来的n行,每行有m个数字(非“0”即“1”)。每两个数字之间用空格隔开。

对于30%的数据,有n,m≤100

对于60%的数据,有n,m≤1000

对于100%的数据,有n,m≤2500

 

输出格式:

 

只有一个整数——猫猫一口下去可以吃掉的鱼的数量,占一行,行末有回车。

 

输入输出样例

输入样例#1: 复制
4 6
0 1 0 1 0 0
0 0 1 0 1 0
1 1 0 0 0 1
0 1 1 0 1 0
输出样例#1: 复制
3

说明

右上角的

1 0 0
0 1 0
0 0 1

******DP题,这道题可以看成最大正方形的提高版,求两种扫描线,上面那种是s数组求左面的0个数,下面的那种是求s右面0的个数注意列数加或减1
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 int i,j,n,m,ans = 0,a[2505][2505],f[2505][2505],s[2505][2505],c[2505][2505];
 7 int main()
 8 {
 9     scanf("%d %d",&n,&m);
10     for(i = 1;i <= n;i++)
11     {
12         for(j = 1;j <= m;j++)
13         {
14             scanf("%d",&a[i][j]);
15             if(a[i][j] == 0)
16             {
17                 s[i][j] = s[i][j - 1] + 1;
18                 c[i][j] = c[i - 1][j] + 1;
19             }
20             else
21             {
22                 f[i][j] = min(f[i - 1][j - 1],min(s[i][j - 1],c[i - 1][j])) + 1;
23             }
24             ans = max(ans,f[i][j]);
25         }
26     }
27     memset(f,0,sizeof(f));
28     memset(s,0,sizeof(s));
29     for(i = 1;i <= n;i++)
30     {
31         for(j = m;j >= 1;j--)
32         {
33             if(a[i][j] == 0)
34             {
35                 s[i][j] = s[i][j + 1] + 1;
36                 c[i][j] = c[i - 1][j] + 1;
37             }
38             else
39             {
40                 f[i][j] = min(f[i - 1][j + 1],min(s[i][j + 1],c[i - 1][j])) + 1;
41             }
42             ans = max(ans,f[i][j]);
43         }
44     }
45     printf("%d",ans);
46     return 0;
47 }


猜你喜欢

转载自www.cnblogs.com/rax-/p/9933700.html