【花样枚举】bzoj 1177 apio2009采油区域
来源:互联网 发布:linux 文件系统介绍 编辑:程序博客网 时间:2024/04/28 18:38
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1177
题目大意:给你一个矩阵,让你选出三个边长为k且互不重叠的正方形使得所有正方形内的数的和最大
这题正解还真是枚举……不过这个枚举很厉害的说
最暴力就是枚举三个正方形的位置,不过一定不会AC……
但是多思考一下会发现一件事情:任意两条直线都可以把矩阵分为三部分,且可以做到将三个正方形分别分到三部分里
1.可以通过两条互相垂直的线分成三块,如下图
2.可以通过两条平行的平行的线分成三块,如下图
知道了这个可以做什么呢?反正正方形一定在被分出来的每一部分里对吧……所以我们可以通过维护每一部分的正方形的最大值来快速寻找每个部分里的正方形
枚举两条线,然后通过 二维前缀和+dp 或者 二维前缀和+萝比特酱(lowbit) 维护下最大值就可以了,dp的维护方法就是xx[i][j]代表以(i,j)为右下角,(1,1)为左上角的区域内的最大值,然后再开三个类似的数组……
贴代码(dp)
#include <cstdio>#include <cstring>#include <iostream>#define INF 2147483647#define MAXN 2000using namespace std;int a[MAXN][MAXN];int s[MAXN][MAXN];int xx[MAXN][MAXN];int xy[MAXN][MAXN];int yx[MAXN][MAXN];int yy[MAXN][MAXN];int lx[MAXN];int ly[MAXN];int n,m,k;int ans = 0;int p,q;int o;int read(){ int x = 0; char w; w = getchar(); while(w >= '0' && w <= '9') { x *= 10; x += w - '0'; w = getchar(); } return x;}int nico(int x,int y){ return s[x][y-1] + s[x-1][y] - s[x-1][y-1] + a[x][y];}int poi(int x,int y){ if(x < k || y < k) return 0; return s[x-k][y-k] - s[x][y-k] - s[x-k][y] + s[x][y];}void dp(){ for(int i = k;i <= o;i ++) { for(int j = k;j <= o;j ++) { xx[i][j] = max(xx[i-1][j],xx[i][j-1]); xx[i][j] = max(xx[i][j],poi(i,j)); } } for(int i = k;i <= o;i ++) { for(int j = o;j >= k;j --) { xy[i][j] = max(xy[i-1][j],xy[i][j+1]); xy[i][j] = max(xy[i][j],poi(i,j)); } } for(int i = o;i >= k;i --) { for(int j = k;j <= o;j ++) { yx[i][j] = max(yx[i+1][j],yx[i][j-1]); yx[i][j] = max(yx[i][j],poi(i,j)); } } for(int i = o;i >= k;i --) { for(int j = o;j >= k;j --) { yy[i][j] = max(yy[i+1][j],yy[i][j+1]); yy[i][j] = max(yy[i][j],poi(i,j)); } } for(int i = 1;i <= o;i ++) { for(int j = 1;j <= o;j ++) { lx[i] = max(lx[i],poi(i,j) ); ly[i] = max(ly[i],poi(j,i) ); } } return ;}void sol(){ int minn; for(int i = k;i <= o;i ++) { for(int j = k;j <= o;j ++) { ans = max(ans,xx[i][j] + xy[i][j+k] + yx[i+k][m]); ans = max(ans,xx[i][j] + yx[i+k][j] + xy[n][j+k]); ans = max(ans,xy[i][j+k] + yy[i+k][j+k] + xx[n][j]); ans = max(ans,yx[i+k][j] + yy[i+k][j+k] + xx[i][m]); } } for(int i = k;i <= n;i ++) for(int j = i+k;j <= n-k;j ++) ans = max(ans,xx[i][m] + lx[j] + yx[j+k][m]); for(int i = k;i <= m;i ++) for(int j = i+k;j <= m-k;j ++) ans = max(ans,xx[n][i] + ly[j] + xy[n][j+k]); return ;}int main(){ n = read(); m = read(); k = read(); o = max(n,m); for(int i = 1;i <= n;i ++) for(int j = 1;j <= m;j ++) a[i][j] = read(); s[i][j] = nico(i,j); dp(); sol(); cout << ans; return 0;}/*6 6 21 0 1 0 1 20 1 0 2 2 11 2 0 2 2 00 1 1 0 2 22 2 1 2 1 10 2 0 0 1 2*/
0 0
- 【花样枚举】bzoj 1177 apio2009采油区域
- [APIO2009]采油区域(枚举+递推)
- 【BZOJ 1177】 [Apio2009]Oil
- BZOJ-1177 [Apio2009]Oil
- BZOJ 1177 [Apio2009]Oil
- [BZOJ 1177][Apio2009]Oil:DP
- 【动态规划】采油区域
- 【动态规划】采油区域
- 采油区域-APIO 2009
- bzoj 1177: [Apio2009]Oil (DP)
- BZOJ 1179: [Apio2009]Atm
- BZOJ P1179[Apio2009]Atm
- BZOJ P1177[Apio2009]Oil
- BZOJ 1179: [Apio2009]Atm
- BZOJ 1179[Apio2009]Atm
- 蓝桥-ALGO-44-采油区域
- 【APIO2009T1】采油区域-分类讨论+动态规划
- [Bzoj 1177][Apio2009] Oil 前缀和+递推
- codevs2776题解:寻找代表元
- C++基础编程----4.3表达式
- Android 触摸事件的分发与处理流程:onInterceptTouchEvent和onTouchEvent
- Cocos2d-x利用Unity轻松快速设计复杂2D地形
- **LeetCode-Paint Fence
- 【花样枚举】bzoj 1177 apio2009采油区域
- Ubuntu安装SSH时出现软件包openssh-server还没有可供安装的
- thinkphp——上传新图并且删除旧图的操作(商品的更新操作 upd)
- openwrt 设置路由器定时重启 计划任务
- .NET加密技术概述
- 蒋介石为何青睐德国军事顾问
- E: Encountered a section with no Package: header
- 俄国、波兰的二战史
- Codevs1653 种树2