洛谷P2219 [HAOI2007]修筑绿化带(单调队列)

本文介绍了一种解决矩阵中寻找最小权值路径的问题算法,通过先枚举行再枚举列,利用单调队列更新最小权值,最终得到最优解。代码实现详细,适合算法学习与竞赛准备。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

 

啧……明明以前做到过这种类型的题结果全忘了……

这种矩阵的,一般都是先枚举行,然后对列进行一遍单调队列,搞出右下角在每一行中合法位置时的最小权值

再枚举列,对行做一遍单调队列,用之前搞出来的最小权值再做一次单调队列,更新答案

感觉很难讲清楚啊……看代码好了……虽然代码可能更不清楚……

 1 //minamoto
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 5 char buf[1<<21],*p1=buf,*p2=buf;
 6 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
 7 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
 8 inline int read(){
 9     #define num ch-'0'
10     char ch;bool flag=0;int res;
11     while(!isdigit(ch=getc()))
12     (ch=='-')&&(flag=true);
13     for(res=num;isdigit(ch=getc());res=res*10+num);
14     (flag)&&(res=-res);
15     #undef num
16     return res;
17 }
18 const int N=1005;
19 int sum[N][N],sum1[N][N],sum2[N][N],q[N],mn[N][N];
20 int n,m,A,B,C,D,h,t,res;
21 void init(){
22     for(int i=C+1;i<n;++i){
23         h=1,t=0;
24         for(int j=D+1;j<m;++j){
25             while(h<=t&&sum2[i][q[t]]>=sum2[i][j]) --t;
26             q[++t]=j;
27             if(q[h]<=j-B+D+1) ++h;
28             mn[i][j]=sum2[i][q[h]];
29         }
30     }
31 }
32 void solve(){
33     for(int j=D+1;j<m;++j){
34         h=1,t=0;
35         for(int i=C+1;i<n;++i){
36             while(h<=t&&mn[q[t]][j]>=mn[i][j]) --t;
37             q[++t]=i;
38             if(q[h]<=i-A+C+1) ++h;
39             cmax(res,sum1[i+1][j+1]-mn[q[h]][j]);
40         }
41     }
42 }
43 int main(){
44 //    freopen("testdata.in","r",stdin);
45     n=read(),m=read(),A=read(),B=read(),C=read(),D=read();
46     if(n==2||m==2) return puts("0"),0;
47     for(int i=1;i<=n;++i) for(int j=1;j<=m;++j)
48     sum[i][j]=read()+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
49     for(int i=A;i<=n;++i) for(int j=B;j<=m;++j)
50     sum1[i][j]=sum[i][j]-sum[i-A][j]-sum[i][j-B]+sum[i-A][j-B];
51     for(int i=C;i<=n;++i) for(int j=D;j<=m;++j)
52     sum2[i][j]=sum[i][j]-sum[i-C][j]-sum[i][j-D]+sum[i-C][j-D];
53     init(),solve();
54     printf("%d\n",res);
55     return 0;
56 }

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9762165.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值