[APIO2009]采油区域

https://zybuluo.com/ysner/note/1144701

题面

给出一个\(n×m\)的矩阵。请在其中选择\(3\)个互不相交的,大小恰为\(k×k\) 的子矩阵,使得子矩阵的权值和最大。

  • \(n\leq1500,m\leq1500\)

    解析

    这题和CJOJ2501很像呢。。。

    看到题,本能地打了一个\(DP\),然后至今调不出来。。。

解法一

矩阵对应端点为其右下方端点,\(S[i][j]\)即为其面积。

\(f[i][j]\)表示选择\((i,j)\)这个点对应矩阵,并且还选择\(1~0\)个矩阵的最优解。

\(upmx\)表示当前点可转移的上方所有点对应值\(S\)最优值。\(lfmx[j]\)表示前\(j\)列中的最优矩阵\(S\)值

那么有\(f[i][j]=max(upmx,lfmx[j-k])+S[i][j]\)

最巧妙的地方,我们最多可以选择3个矩阵,那么是不是可以看做选一个\(f[t1][t2]\)加上一个\(S[i][j]\)?

\(upmx\)表示当前点可转移的上方所有点对应值\(f\)最优值。\(lfmx[j]\)表示前\(j\)列中的最优矩阵\(f\)值

那么有\(ans[i][j]=max(upmx,lfmx[j-k])+S[i][j]\)

il void Matrix()
{
  fp(i,1,n) fp(j,1,m) a[i][j]=gi()+a[i-1][j]+a[i][j-1]-a[i-1][j-1];//二维前缀和套路
  fp(i,k,n) fp(j,k,m) s[i][j]=a[i][j]+a[i-k][j-k]-a[i-k][j]-a[i][j-k];//以(i,j)为右下端点的k*k矩阵的面积(还是套路,自己画图就知道了)
}
il void Solve()
{
  upmx=0;memset(lfmx,0,sizeof(lfmx));
  fp(i,k,n)
    {
      fp(j,k,m) upmx=max(upmx,s[i-k][j]);//i代表行,j代表列,该矩阵上面 底最下到该矩形的上边的矩形
      fp(j,k,m)
    {
          lfmx[j]=max(lfmx[j-1],lfmx[j]);//维护左边的最大权值矩形
          lfmx[j]=max(lfmx[j],s[i][j]);//维护上边的最大权值矩形
      f[i][j]=max(upmx,lfmx[j-k])+s[i][j];//累计合法情况
    }
    }//搞完两个矩阵的情况
  upmx=0;memset(lfmx,0,sizeof(lfmx));//lfmx变成维护f,f代表两个矩形,我们依据上面的套路继续选取s(1个)+f(2个)
 fp(i,k,n)
    {
      fp(j,k,m) upmx=max(upmx,f[i-k][j]);
      fp(j,k,m)
    {
          lfmx[j]=max(lfmx[j-1],lfmx[j]);
      lfmx[j]=max(lfmx[j],f[i][j]);
      ans=max(ans,max(upmx,lfmx[j-k])+s[i][j]);
    }
    }//搞完三个矩阵的矩阵
 //最后补充一句,在当前矩阵左上方选取的矩阵对当前矩阵没有影响
}
int main()
{
  n=gi();m=gi();k=gi();
  Matrix();
  ans=0;
  Solve();
  printf("%d\n",ans);
    return 0;
}

解法二

取三个互不相交的矩形?

何尝不是把整个图形分为三块,然后在每一块中取最大值?

分成三块有六种情况:

于是对应维护以每个点为右下角的\(k*k\)矩形权值和。

据此,可以维护每个点左上\(a\)、左下\(c\)、右上\(b\)、右下\(d\)部分的权值和。

然后枚举中间点(两条直线的交线,或者中间矩形的右下角),不断取\(max\)统计即可。

// luogu-judger-enable-o2
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define ll long long
#define re register
#define il inline
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int N=2100;
int n,m,k,mp[N][N],a[N][N],b[N][N],c[N][N],d[N][N],ans;
il int gi()
{
  re int x=0,t=1;
  re char ch=getchar();
  while((ch<‘0‘||ch>‘9‘)&&ch!=‘-‘) ch=getchar();
  if(ch==‘-‘) t=-1,ch=getchar();
  while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-48,ch=getchar();
  return x*t;
}
int main()
{
  n=gi();m=gi();k=gi();
  fp(i,1,n) fp(j,1,m) mp[i][j]=mp[i-1][j]+mp[i][j-1]-mp[i-1][j-1]+gi();
  fq(i,n,k) fq(j,m,k) mp[i][j]-=(mp[i-k][j]+mp[i][j-k]-mp[i-k][j-k]);
  fp(i,k,n) fp(j,k,m) a[i][j]=max(mp[i][j],max(a[i-1][j],a[i][j-1]));
  fp(i,k,n) fq(j,m,k) b[i][j]=max(mp[i][j],max(b[i-1][j],b[i][j+1]));
  fq(i,n,k) fp(j,k,m) c[i][j]=max(mp[i][j],max(c[i+1][j],c[i][j-1]));
  fq(i,n,k) fq(j,m,k) d[i][j]=max(mp[i][j],max(d[i+1][j],d[i][j+1]));
  fp(i,k,n-k) fp(j,k,m-k) ans=max(ans,a[i][m]+c[i+k][j]+d[i+k][j+k]);
  fp(i,k,n-k) fp(j,k,m-k) ans=max(ans,a[i][j]+b[i][j+k]+c[i+k][m]);
  fp(i,k,n-k) fp(j,k,m-k) ans=max(ans,a[n][j]+b[i][j+k]+d[i+k][j+k]);
  fp(i,k,n-k) fp(j,k,m-k) ans=max(ans,a[i][j]+b[n][j+k]+c[i+k][j]);
  fp(i,k,n-k) fp(j,k+k,m-k) ans=max(ans,a[n][j-k]+b[n][j+k]+mp[i][j]);
  fp(i,k+k,n-k) fp(j,k,m-k) ans=max(ans,a[i-k][m]+c[i+k][m]+mp[i][j]);
  printf("%d\n",ans);
  return 0;
}

原文地址:https://www.cnblogs.com/yanshannan/p/9028868.html

时间: 2024-10-20 04:43:53

[APIO2009]采油区域的相关文章

洛谷P3625 - [APIO2009]采油区域

Portal Description 给出一个\(n\times m(n,m\leq1500)\)的矩阵,从中选出\(3\)个互不相交的\(k\times k\)方阵,使得被选出的数的和最大. Solution 奇怪做法... 三个矩形分别在三个部分中,把矩形划分成三部分只有这六种.首先搞出\(s[i][j]\)表示以\((i,j)\)为右下角的\(k\times k\)方阵的和,然后搞出\(f_1[i][j]\)表示\((1,1)-(i,j)\)中\(s\)的最大值,\(f_2[i][j]\)

洛谷 P3625 [APIO2009]采油区域【枚举】

参考:https://blog.csdn.net/FAreStorm/article/details/49200383 没有技术含量但是难想难写,枚举情况图详见参考blog懒得画了 #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N=1505; int n,m,k,a[N][N],b[N][N],c[N][N],d[N][N],s[N][N],p

【BZOJ 1177】 [Apio2009]Oil

1177: [Apio2009]Oil Time Limit: 15 Sec  Memory Limit: 162 MB Submit: 1044  Solved: 404 [Submit][Status][Discuss] Description 采油区域 Siruseri政府决定将石油资源丰富的Navalur省的土地拍卖给私人承包商以建立油井.被拍卖的整块土地为一个矩形区域,被划分为M×N个小块. Siruseri地质调查局有关于Navalur土地石油储量的估测数据.这些数据表示为M×N个非

[Bzoj 1177][Apio2009] Oil 前缀和+递推

1177: [Apio2009]Oil Time Limit: 15 Sec Memory Limit: 162 MB Submit: 1569 Solved: 632 [Submit][Status][Discuss] Description 采油区域 Siruseri政府决定将石油资源丰富的Navalur省的土地拍卖给私人承包商以建立油井.被拍卖的整块土地为一个矩形区域,被划分为M×N个小块. Siruseri地质调查局有关于Navalur土地石油储量的估测数据.这些数据表示为M×N个非负整

[BZOJ1177][BZOJ1178][BZOJ1179]APIO2009解题报告

抱着好奇心态去开始做APIO的往年试题感受一下难度 Oil Description 采油区域 Siruseri政府决定将石油资源丰富的Navalur省的土地拍卖给私人承包商以建立油井.被拍卖的整块土地为一个矩形区域,被划分为M×N个小块. Siruseri地质调查局有关于Navalur土地石油储量的估测数据.这些数据表示为M×N个非负整数,即对每一小块土地石油储量的估计值. 为了避免出现垄断,政府规定每一个承包商只能承包一个由K×K块相连的土地构成的正方形区域. AoE石油联合公司由三个承包商组

【BZOJ】【1177】【APIO2009】Oil

DP 找出三个正方形,可以转化为将整个油田切成三个矩形块,每块中各找一个正方形区域,切的形式只有6种,分类更新ans即可 题解:http://trinklee.blog.163.com/blog/static/238158060201482371229105/ 另:这题一般的快速读入不知为何会RE,但是题解里这位大神的快速读入就能AC……跪了跪了 1 /************************************************************** 2 Problem

【opencv入门之二】感兴趣区域ROI,线性混合addWeighted

参考网站: http://blog.csdn.net/poem_qianmo/article/details/20911629 1.感兴趣区域ROI //[2]定义一个Mat类型并给其设定ROI区域 Mat imageROI = srcImage1( Rect(200, 250, logoImage.cols, logoImage.rows )); //[3]加载掩摸(必须是灰度图) Mat mask = imread( "dota_logo.jpg", 0 ); //[4]将掩摸拷贝

数据库表:区域表system_district

区域表[system_district] 数据模型 建表脚本 -- ---------------------------- -- Table structure for system_district -- ---------------------------- DROP TABLE IF EXISTS `system_district`; CREATE TABLE `system_district` (   `district_id` bigint(20) unsigned NOT NUL

Halcon学习之六:获取Image图像中Region区域的特征参数

area_center_gray ( Regions, Image : : : Area, Row, Column )    计算Image图像中Region区域的面积Area和重心(Row,Column). cooc_feature_image ( Regions, Image : : LdGray, Direction : Energy,Correlation, Homogeneity, Contrast )   计算共生矩阵和推导出灰度特征值 Direction:灰度共生矩阵计算的方向