• 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

    说明/提示

    右上角的

    1 0 0
    0 1 0
    0 0 1

    思路
      考虑这样一个问题:如果以 f[i][j][1|0] 来表示取到第 (i, j) 个位置时所能取到的最长的对角线长度,0表示左上到右下,1表示右上到左下方向,什么时候怎样来更新 f 的值。
      首先如果以 之前那道最大正方形的方法来做,只能过第一个点 1 1 0 这个数据。因为会发现这道题比最大正方形多了一个限制条件,就是在这个对角线确定的大矩形中,除了这条对角线之外不能有多余的1.
      所以在从右上或左上转移时,要多加一个这个条件对状态的影响。
      这个条件有什么影响?
      注意到因为动态规划是由 1 ~ n 这样来推理,所以可以分析在边界 1 时的影响即可。
      对于以下样例分析
      1 0 0
      0 1 0
      0 0 1
      当 i = 1, j = 1 时,显然 f = 1
      当 i = 2, j = 2 时,如果 a[2][2] 的上方和右方都没有 1 ,则 f[i][j] = f[i-1][j-1] + 1 ;
                  如果 a[2][2] 的右方和上方有 1 ,显然 f[i][j] = 1 且应该作为一段新的开始。
      由是可以推到 n 。

    CODE
    #include <bits/stdc++.h>
    #define dbg(x) cout << #x << "=" << x << endl
    #define eps 1e-8
    #define pi acos(-1.0)

    using namespace std;
    typedef long long LL;

    const int inf = 0x3f3f3f3f;

    template<class T>inline void read(&res)
    {
        char c;T flag=1;
        while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
        while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
    }

    namespace _buff {
        const size_t BUFF = 1 << 19;
        char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
        char getc() {
            if (ib == ie) {
                ib = ibuf;
                ie = ibuf + fread(ibuf, 1, BUFF, stdin);
            }
            return ib == ie ? -1 : *ib++;
        }
    }

    int qread() {
        using namespace _buff;
        int ret = 0;
        bool pos = true;
        char c = getc();
        for (; (< '0' || c > '9') && c != '-'; c = getc()) {
            assert(~c);
        }
        if (== '-') {
            pos = false;
            c = getc();
        }
        for (; c >= '0' && c <= '9'; c = getc()) {
            ret = (ret << 3) + (ret << 1) + (^ 48);
        }
        return pos ? ret : -ret;
    }

    const int maxn = 2577;

    int n,m;
    int a[maxn][maxn];
    int f[maxn][maxn][2];

    int main()
    {
        //freopen("data.txt", "r", stdin);
        read(n);
        read(m);
        for ( int i = 1; i <= n; ++) {
            for ( int j = 1; j <= m; ++) {
                read(a[i][j]);
            }
        }
        int ans = 0;
        for ( int i = 1; i <= n; ++) {
            for ( int j = 1; j <= m; ++) {
                if(a[i][j]) {
                    int up = 0, rig = 0;
                    for ( int k = i - 1; k >= 1; --) {
                        if(a[k][j]) {
                            break;
                        }
                        ++up;
                    }
                    for ( int k = j + 1; k <= m; ++) {
                        if(a[i][k]) {
                            break;
                        }
                        ++rig;
                    }
                    
                    f[i][j][1] = min(f[- 1][+ 1][1], min(up, rig)) + 1;
                    //f[i][j][1] = min(f[i - 1][j + 1][1], min(up, rig)) + 1;
                }
                //printf("f[%d][%d]:%d ",i, j, f[i][j][0]);
                ans = max(ans, max(f[i][j][0], f[i][j][1]));
            }
            for ( int j = m; j >= 1; --) {
                int up = 0, lef = 0;
                if(a[i][j]) {
                    for ( int k = i - 1; k >= 1; --) {
                        if(a[k][j]) {
                            break;
                        }
                        ++up;
                    }
                    for ( int k = j - 1; k >= 1; --) {
                        if(a[i][k]) {
                            break;
                        }
                        ++lef;
                    }
                    
                    f[i][j][0] = min(f[- 1][- 1][0], min(up, lef)) + 1;
                    // if(i == 3 && j == 6) {
                    //     printf("up:%d lef:%d f[3][6][0]:%d ",up, lef, f[3][6][0]);
                    // }
                    // if(i == 2 && j == 5) {
                    //     printf("up:%d lef:%d f[2][5][0]:%d ",up, lef, f[2][5][0]);
                    // }
                    // if(i == 1 && j == 4) {
                    //     printf("up:%d lef:%d f[1][4][0]:%d ",up, lef, f[1][4][0]);
                    // }
                }
                ans = max(ans, max(f[i][j][0], f[i][j][1]));
            }
            
        }
        cout << ans << endl;
        return 0;
    }
  • 相关阅读:
    unity的#pragma strict,#pragma downcast等指令分享
    Unity3d 添加多相机后编译警告
    Invoke计时器
    unity3d UI自动适合屏幕分辨率
    实现卷轴效果的脚本
    .unity3d格式的导出与加载
    Linux 网络编程
    姿态解算基本完成,程序编写笔记
    验证网络上四元数的正确性
    2440 模拟IIC 可以读取 L3G4200D ,ADXL345
  • 原文地址:https://www.cnblogs.com/orangeko/p/12532328.html
Copyright © 2020-2023  润新知