Luogu2216 [HAOI2007]理想的正方形

本文解析了如何使用二维滑动窗口技巧解决Luogu P2216的理想正方形问题,通过两次窗口操作找到矩阵中n*n区域内最大值与最小值之差的最小值。适合理解矩阵操作和动态规划的应用。

原题链接:https://www.luogu.com.cn/problem/P2216

理想的正方形

题目描述

有一个a * b的整数组成的矩阵,现请你从中找出一个 n * n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。

输入格式

第一行为3个整数,分别表示a,b,n的值

第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。

输出格式

仅一个整数,为ab矩阵中所有“nn正方形区域中的最大整数和最小整数的差值”的最小值。

输入输出样例

输入 #1
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
输出 #1
1

说明/提示

问题规模

(1)矩阵中的所有数都不超过1,000,000,000

(2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10

(3)100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100

题解

二维的滑动窗口,先对每一行做一次横向的滑动窗口,求出每一行长为 n n n的窗口滑过的最小/大值,再对求出的最小/大值做一次纵向的滑动窗口,这样求出的就是二维的 n × n n\times n n×n的窗口覆盖的最小/大值。

代码

看起来多,实际上都是复制粘贴的,一遍过针不戳。

#include<bits/stdc++.h>
using namespace std;
const int M=1e3+5;
int n,a,b,que[M],sqr[M][M],mn[M][M],mx[M][M],mn2[M][M],mx2[M][M],head,tail;
void hori(int x)
{
    que[head=tail=1]=1;if(n==1)mn[x][1]=sqr[x][1];
    for(int i=2;i<=b;++i)
    {
        for(;sqr[x][que[tail]]>=sqr[x][i]&&tail>=head;--tail);
        que[++tail]=i;
        for(;i-que[head]+1>n&&head<=tail;++head);
        if(i>=n)mn[x][i]=sqr[x][que[head]];
    }
    que[head=tail=1]=1;if(n==1)mx[x][1]=sqr[x][1];
    for(int i=2;i<=b;++i)
    {
        for(;sqr[x][que[tail]]<=sqr[x][i]&&tail>=head;--tail);
        que[++tail]=i;
        for(;i-que[head]+1>n&&head<=tail;++head);
        if(i>=n)mx[x][i]=sqr[x][que[head]];
    }
}
void verti(int x)
{
    que[head=tail=1]=1;if(n==1)mn2[1][x]=mn[1][x];
    for(int i=2;i<=a;++i)
    {
        for(;mn[que[tail]][x]>=mn[i][x]&&tail>=head;--tail);
        que[++tail]=i;
        for(;i-que[head]+1>n&&head<=tail;++head);
        if(i>=n)mn2[i][x]=mn[que[head]][x];
    }
    que[head=tail=1]=1;if(n==1)mx2[1][x]=mx[1][x];
    for(int i=2;i<=a;++i)
    {
        for(;mx[que[tail]][x]<=mx[i][x]&&tail>=head;--tail);
        que[++tail]=i;
        for(;i-que[head]+1>n&&head<=tail;++head);
        if(i>=n)mx2[i][x]=mx[que[head]][x];
    }
}
void in()
{
    scanf("%d%d%d",&a,&b,&n);
    for(int i=1;i<=a;++i)for(int j=1;j<=b;++j)scanf("%d",&sqr[i][j]);
}
void ac()
{
    for(int i=1;i<=a;++i)hori(i);
    for(int i=n;i<=b;++i)verti(i);
    int ans=INT_MAX;
    for(int i=n;i<=a;++i)for(int j=n;j<=b;++j)ans=min(ans,mx2[i][j]-mn2[i][j]);
    printf("%d\n",ans);
}
int main()
{
    in(),ac();
    system("pause");
}
【负荷预测】基于VMD-CNN-LSTM的负荷预测研究(Python代码实现)内容概要:本文介绍了基于变分模态分解(VMD)、卷积神经网络(CNN)和长短期记忆网络(LSTM)相结合的VMD-CNN-LSTM模型在负荷预测中的研究与应用,采用Python代码实现。该方法首先利用VMD对原始负荷数据进行分解,降低序列复杂性并提取不同频率的模态分量;随后通过CNN提取各模态的局部特征;最后由LSTM捕捉时间序列的长期依赖关系,实现高精度的负荷预测。该模型有效提升了预测精度,尤其适用于非平稳、非线性的电力负荷数据,具有较强的鲁棒性和泛化能力。; 适合人群:具备一定Python编程基础和深度学习背景,从事电力系统、能源管理或时间序列预测相关研究的科研人员及工程技术人员,尤其适合研究生、高校教师及电力行业从业者。; 使用场景及目标:①应用于日前、日内及实时负荷预测场景,支持智慧电网调度与能源优化管理;②为研究复合型深度学习模型在非线性时间序列预测中的设计与实现提供参考;③可用于学术复现、课题研究或实际项目开发中提升预测性能。; 阅读建议:建议读者结合提供的Python代码,深入理解VMD信号分解机制、CNN特征提取原理及LSTM时序建模过程,通过实验调试参数(如VMD的分解层数K、惩罚因子α等)优化模型性能,并可进一步拓展至风电、光伏等其他能源预测领域。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值