[二维DP] 洛谷P1736 创意吃鱼法(预处理)

题目

LP1736

思路

本题作为一道提高+/省选-的题,基本思路是自己想出来的,拿了90,然后有一个小bug一直没发现,拿来标程对比,改了这个bug然后AC,还是很开心的。


首先,借鉴最大正方形的经验,这种题应该下手画图,不出意外,通过画图找到了状态转移的规律。
首先我们将d(i,j)定义为,(i,j)为一个对角线的右下角或左下角时,最长的对角线代表正方形内无其它1的对角线长度。
这里我们先拿右下角分析。
这里写图片描述
我们定义lf[i][j],元素(i,j)的左边第一个1的横坐标,uf[i][j],元素(i,j)上边第一个1的纵坐标。由图可知,设对角线左上角坐标为(a,b),d[i][j] = d[i-1][j-1]+1当且仅当uf[i][j] < a && lf[i][j] < b。而此处对角线左上角的坐标,可以根据d[i-1][j-1]的值来确定。这就明确了状态转移的条件。
拿左下角分析时,有两种方法,要么直接将图像左右反转,然后再用一遍之前的代码,要么再根据uf和lf制定另一个状态转移条件判断。第一种是偷懒的办法。。我之前试了。。洛谷最后一个点会TLE,第二种用uf和lf套来套去,在此处就不说了。


确定对角线另一端的坐标。
可以根据tl=d[i-1][j-1]或d[i-1][j+1],而l [1,tl],将l从大到小遍历,每次的另一端坐标就是d[i-l][j-l]或d[i-l][j+l]。
注意此处不能直接用tl而不用l遍历小于等于tl的每一个值,本题只有一个数据点能反映这个事实,这也是我得90的bug,考虑如下情况:
0 0 0 0 0 0 0
1 1 0 0 1 0 0
0 0 1 0 0 0 0
0 0 0 1 0 0 0
1 0 0 0 1 0 0
0 1 0 0 0 1 0
1 0 0 0 0 0 1
显然在考虑加粗体1时,如果直接用tl=4,直接就否定了这个点作为右小角端点的权利。而l=3时,这个点可以,从而在整个图形中得到了长度为5的合法对角线。

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;

const int maxn = 2500 + 10;
int n, m, G[maxn][maxn], d[maxn][maxn], lf[maxn][maxn], uf[maxn][maxn];

int main() {
    scanf("%d%d", &n, &m);
    _rep(i, 1, n) _rep(j, 1, m) scanf("%d", &G[i][j]);

    // 打表lf和uf
    int last;
    _rep(i, 1, n) {
        last = 0;
        _rep(j, 1, m)
            if (G[i][j] == 1) {
                lf[i][j] = last;
                last = j;
            }
            else {
                lf[i][j] = last;
            }
    }

    _rep(j, 1, m) {
        last = 0;
        _rep(i, 1, n)
            if (G[i][j] == 1) {
                uf[i][j] = last;
                last = i;
            }
            else {
                uf[i][j] = last;
            }
    }

    int ans = 0;
    // (i,j)作为一个对角线的右下角时
    _rep(i,1,n)
        _rep(j, 1, m)
            if (G[i][j] == 1) {
                d[i][j] = 1;
                int tl = d[i - 1][j - 1];
                for (int l = tl; l >= 1; l--) {
                    if (uf[i][j] < i - l && lf[i][j] < j - l) {
                        d[i][j] = l + 1;
                        break;
                    }
                }
                ans = max(ans, d[i][j]);
            }

    //(i,j)作为一个对角线的左下角时
    _rep(i, 1, n)
        for(int j = m; j>=1; j--)
            if (G[i][j] == 1) {
                d[i][j] = 1;
                int tl = d[i - 1][j + 1];
                for (int l = tl; l >= 1; l--) {
                    if (uf[i][j + l] == i - l && lf[i][j + l] == j && uf[i][j] < i - l && lf[i - l][j + l] < j) {
                        d[i][j] = l + 1;
                        break;
                    }
                }
                ans = max(ans, d[i][j]);
            }


    printf("%d\n", ans);

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二维图像预处理是数字图像处理中的一个重要步骤,常见的预处理操作包括图像增强、滤波、二值化、边缘检测等。MATLAB是一种常用的数字图像处理工具,提供了丰富的图像处理函数和工具箱,可以方便地进行各种预处理操作。 下面以图像增强和滤波为例,介绍MATLAB中的二维图像预处理操作。 1. 图像增强 图像增强的目的是改善图像的质量,使得图像更加清晰、明亮、具有更好的对比度等。常用的图像增强方法包括直方图均衡化、对比度拉伸、锐化等。 直方图均衡化是一种常用的图像增强方法,可以使得图像的对比度更加明显,同时使得图像的灰度分布更加均匀。在MATLAB中可以使用histeq函数实现直方图均衡化,示例代码如下: ```matlab img = imread('lena.jpg'); % 读取图像 img_eq = histeq(img); % 直方图均衡化 imshow(img), title('原图像'); figure, imshow(img_eq), title('均衡化后的图像'); ``` 对比度拉伸是一种简单的图像增强方法,可以通过调整图像的灰度值范围来增加对比度。在MATLAB中可以使用imadjust函数实现对比度拉伸,示例代码如下: ```matlab img = imread('lena.jpg'); % 读取图像 img_adj = imadjust(img,[0.2,0.8],[]); % 对比度拉伸 imshow(img), title('原图像'); figure, imshow(img_adj), title('对比度拉伸后的图像'); ``` 2. 滤波 滤波是一种常用的图像处理方法,可以去除图像中的噪声、平滑图像等。常用的滤波方法包括均值滤波、中值滤波、高斯滤波等。 均值滤波是一种简单的滤波方法,可以通过计算像素周围的平均值来平滑图像。在MATLAB中可以使用fspecial函数生成均值滤波器,使用imfilter函数进行滤波操作,示例代码如下: ```matlab img = imread('lena.jpg'); % 读取图像 h = fspecial('average',3); % 生成3x3的均值滤波器 img_filt = imfilter(img,h); % 均值滤波 imshow(img), title('原图像'); figure, imshow(img_filt), title('均值滤波后的图像'); ``` 中值滤波是一种非线性滤波方法,可以有效地去除图像中的椒盐噪声等。在MATLAB中可以使用medfilt2函数进行中值滤波操作,示例代码如下: ```matlab img = imread('lena.jpg'); % 读取图像 img_noisy = imnoise(img,'salt & pepper',0.02); % 添加椒盐噪声 img_filt = medfilt2(img_noisy); % 中值滤波 imshow(img_noisy), title('添加噪声后的图像'); figure, imshow(img_filt), title('中值滤波后的图像'); ``` 以上是MATLAB中常用的二维图像预处理操作,这些操作可以提高图像的质量,为后续的图像处理任务打下良好的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值