|洛谷|动态规划|P1736 创意吃鱼法

来源:互联网 发布:阿里云如何做代理商 编辑:程序博客网 时间:2024/06/06 13:04

http://www.luogu.org/problem/show?pid=1736

先O(nm)预处理r, l, up数组

分别代表在右边连续出现几个0,在左边连续出现几个0,在上边连续出现几个0

即得转移方程,f[i][j]为以i,j作为正方形的右下顶点的最大吃鱼数

主对角线:f[i][j]=min(f[i-1][j-1],left[i][j-1],up[i-1][j])+1
副对角线:f[i][j]=min(f[i-1][j+1],right[i][j+1],up[i-1][j])+1

注意搜索两条对角线要分开搜索

#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define ms(i,j) memset(i,j, sizeof i);using namespace std;int n,m;bool map[2505][2505];int up[2505][2505], l[2505][2505], r[2505][2505], f[2505][2505];int main(){scanf("%d%d", &n ,&m);for (int i=1;i<=n;i++)for (int j=1;j<=m;j++)scanf("%d", &map[i][j]);ms(up,0); ms(l,0); ms(r,0);for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){if (map[i][j]==0) {up[i][j] = up[i-1][j]+1;l[i][j] = l[i][j-1]+1;}}}for (int i=n;i>0;i--){for (int j=m;j>0;j--){if (map[i][j]==0) {r[i][j] = r[i][j+1]+1;}}}ms(f,0);int ans = 0;for (int i=1;i<=n;i++){for (int j=1;j<=m;j++)if (map[i][j]){f[i][j] = min(f[i-1][j-1], min(up[i-1][j], l[i][j-1]))+1;ans = max(ans, f[i][j]);}}ms(f,0);for (int i=1;i<=n;i++){for (int j=1;j<=m;j++)if (map[i][j]){f[i][j] = min(f[i-1][j+1], min(up[i-1][j], r[i][j+1]))+1;ans = max(ans, f[i][j]);}}printf("%d\n", ans);    return 0;}


0 0
原创粉丝点击