P1736 创意吃鱼法 图的DP

题目描述

回到家中的猫猫把三桶鱼全部转移到了她那长方形大池子中,然后开始思考:到底要以何种方法吃鱼呢(猫猫就是这么可爱,吃鱼也要想好吃法 ^_*)。她发现,把大池子视为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


和上一题求最大正方形一样 并且设dp值也是一样的 之前遇到的dp都是 都是线性dp 最后取值一般为dp【n】

而图的dp有些会有不同 主要关注i j这个点 而不是 1-i 1-j 这个范围 并且最值边dp边更新
这题的dp为 以i j为左(右 )下角的最大对角线长度
注意要dp两遍
#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define LL long long
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define N 2500+5
#define inf 0x3f3f3f3f
int mp[N][N];
int dp[N][N];
int main()
{
    int n,m;
    RII(n,m);
    rep(i,1,n)
    rep(j,1,m)
    RI(mp[i][j]);

    int ans=0;
    rep(i,1,n)
    rep(j,1,m)
    if(mp[i][j])
    {
        int s1=0,s2=0;
        for(int k=i-1;k>=1;k--)
            if(!mp[k][j])s1++;
            else break;
        for(int k=j-1;k>=1;k--)
            if(!mp[i][k])s2++;
            else break;
        dp[i][j]=min(dp[i-1][j-1],min(s1,s2))+1;
        if(dp[i][j]>ans)ans=dp[i][j];
    }

    rep(i,1,n)
    for(int j=m;j>=1;j--)
    if(mp[i][j])
    {
        int s1=0,s2=0;
        for(int k=i-1;k>=1;k--)
            if(!mp[k][j])s1++;
            else break;
        for(int k=j+1;k<=m;k++)
            if(!mp[i][k])s2++;
            else break;
        dp[i][j]=min(dp[i-1][j+1],min(s1,s2))+1;
        if(dp[i][j]>ans)ans=dp[i][j];
    }
    cout<<ans;
}


原文地址:https://www.cnblogs.com/bxd123/p/10518890.html