http://uoj.ac/problem/125 (题目链接)

题意

  在网格上写“NOI”,每个格子上有一些权值,要求覆盖的权值最大。书写有一些规则。

Solution

  将“NOI”分成11个部分,每个部分都是有几个有相同特点的矩形构成的,按列dp前缀最大值优化一下即可。看起来很难码的样子,其实套路都差不多,但是想清楚,一些细节处理到位,平时习惯好一点就可以很快写完辣。

  ${f[p][i][j][k]}$表示第${p}$个部分,正在dp第${i}$列,矩形上边界为${j}$,下边界为${k}$时,最大权值。

  ${mx[p][i][j][k]}$表示的是第${p}$个部分,第${i}$列,与上边界${j}$,下边界${k}$相关的前缀最大值。

  其实比较恶心的就是第二部分,你需要处理出这样的一个前缀最大值:上边界的区间在${[1,j]}$,下边界的区间在${[j+1,k]}$。这个并不好直接求出来,所以我们把它分成两部分:上边界区间在${[1,j]}$,下边界固定在${j+1}$;以及上边界在${[1,j]}$,下边界在${[j,k]}$。这样就非常好处理了。

  第${i}$列那一维再滚动一下就好了。

细节

  初始化什么的。然后${j,k}$按照它们的意义${for}$过去可能会清晰一些吧。

代码

// uoj125
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#define LL long long
#define inf (1ll<<30)
#define MOD 1000000007
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=160,maxm=510;
int a[maxn][maxm],s[maxm][maxn],up[maxn];
int f[12][maxn][maxn],g[12][maxn][maxn],mx[12][maxn][maxn];
int n,m; int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) scanf("%d",&a[i][j]);
for (int j=1;j<=m;j++)
for (int i=1;i<=n;i++) s[j][i]=s[j][i-1]+a[i][j];
for (int i=0;i<=11;i++)
for (int j=0;j<=n+1;j++)
for (int k=0;k<=n+1;k++) f[i][j][k]=g[i][j][k]=mx[i][j][k]=-inf;
for (int i=0;i<=n+1;i++) up[i]=-inf;
int ans=-inf;
for (int i=1;i<=m;i++) {
//第1部分
for (int j=1;j<=n;j++)
for (int k=j;k<=n;k++)
f[1][j][k]=max(g[1][j][k],0)+s[i][k]-s[i][j-1];
//第2部分
for (int j=1;j<=n;j++)
for (int k=n;k>=j;k--) mx[1][j][k]=max(g[1][j][k],mx[1][j][k+1]);
for (int k=1;k<=n;k++) {
up[k]=-inf;
for (int j=1;j<=k;j++) up[k]=max(up[k],g[2][j][k]);
}
for (int k=1;k<=n;k++)
for (int j=1;j<=k;j++) mx[2][j][k]=max(mx[2][j-1][k],g[2][j][k]);
for (int j=1;j<=n;j++)
for (int k=j;k<=n;k++) mx[2][j][k]=max(mx[2][j][k-1],mx[2][j][k]);
for (int j=1;j<=n;j++)
for (int k=j;k<=n;k++)
f[2][j][k]=max(up[j-1],max(mx[1][j][k+1],mx[2][j][k]))+s[i][k]-s[i][j-1];
//第3部分
for (int k=1;k<=n;k++)
for (int j=k;j>=1;j--) mx[2][j][k]=max(mx[2][j+1][k],g[2][j][k]);
for (int j=1;j<=n;j++)
for (int k=j;k<=n;k++)
f[3][j][k]=max(g[3][j][k],mx[2][j+1][k])+s[i][k]-s[i][j-1];
//第4部分
f[4][0][0]=g[4][0][0];
for (int j=1;j<=n;j++)
for (int k=j;k<=n;k++) f[4][0][0]=max(f[4][0][0],g[3][j][k]);
//第5部分
for (int j=1;j<=n;j++)
for (int k=j+2;k<=n;k++) f[5][j][k]=g[4][0][0]+s[i][k]-s[i][j-1];
//第6部分
for (int j=1;j<=n;j++)
for (int k=j+2;k<=n;k++) f[6][j][k]=max(g[5][j][k],g[6][j][k])+s[i][j]-s[i][j-1]+s[i][k]-s[i][k-1];
//第7部分
for (int j=1;j<=n;j++)
for (int k=j+2;k<=n;k++) f[7][j][k]=g[6][j][k]+s[i][k]-s[i][j-1];
//第8部分
f[8][0][0]=g[8][0][0];
for (int j=1;j<=n;j++)
for (int k=j+2;k<=n;k++) f[8][0][0]=max(f[8][0][0],g[7][j][k]);
//第9部分
for (int j=1;j<=n;j++)
for (int k=j+2;k<=n;k++) f[9][j][k]=max(g[9][j][k],g[8][0][0])+s[i][j]-s[i][j-1]+s[i][k]-s[i][k-1];
//第10部分
for (int j=1;j<=n;j++)
for (int k=j+2;k<=n;k++) f[10][j][k]=max(g[10][j][k],g[9][j][k])+s[i][k]-s[i][j-1];
//第11部分
for (int j=1;j<=n;j++)
for (int k=j+2;k<=n;k++) {
f[11][j][k]=max(g[10][j][k],g[11][j][k])+s[i][j]-s[i][j-1]+s[i][k]-s[i][k-1];
ans=max(ans,f[11][j][k]);
}
//滚动
for (int j=1;j<=11;j++)
for (int k=0;k<=n;k++)
for (int l=0;l<=n;l++) g[j][k][l]=f[j][k][l];
}
printf("%d\n",ans);
return 0;
}

【uoj125】 NOI2013—书法家的更多相关文章

  1. BZOJ3241/UOJ125 [Noi2013]书法家

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  2. [Noi2013]书法家

    来自FallDream的博客,未经允许,请勿转载,谢谢. 小E同学非常喜欢书法,他听说NOI2013已经开始了,想题一幅“NOI”的字送给大家. 小E有一张非常神奇的纸,纸可以用一个n 行m 列的二维 ...

  3. BZOJ 3241: [Noi2013]书法家

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3241 题意: 思路:把每个字母分成三部分,两个字母之间还有空的列,所以我一共设了11个状态 ...

  4. P1398 [NOI2013]书法家

    传送门 就是个普及组 $dp$ 合集,把 $NOI$ 从左到右拆成 $9$ 个部分,每个部分都可以分别 $dp$ 除了 $N$ 的中间部分比较恶心以外其他都还好,自己推一下然后就知道转移,就 $N$ ...

  5. luogu P1398 [NOI2013]书法家

    传送门 注意到\(N\ O\ I\)三个字母都可以从左到右拆成三部分,即\(N=\)一个矩形+一堆矩形+一个矩形,\(O=\)一条+两条横的+一条,\(I=\)两条横的+一个矩形+两条横的,所以可以拆 ...

  6. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  7. NOI2013 Day2

    NOI2013 Day2 矩阵游戏 题目描述:设矩阵\(F\) 求\(F[n][m](mod (10^9+7))\) solution: 这题可以求通项解决. 设\(X_i=F[i][m]\), \( ...

  8. bzoj 3242: [Noi2013]快餐店 章鱼图

    3242: [Noi2013]快餐店 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 266  Solved: 140[Submit][Status] ...

  9. bzoj 3240: [Noi2013]矩阵游戏 矩阵乘法+十进制快速幂+常数优化

    3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 613  Solved: 256[Submit][Status] ...

随机推荐

  1. 关于java调用Dll文件的异常 %1 不是有效的 Win32 应用程序。

    这个问题 将java的和编辑器都换成32位

  2. Aria2 Linux 完整安装及使用教程

    Aria2 嘛,主要是用来离线下载,功能强大,支持 http/https 直链.ftp.电驴.磁力链接等等,且可以跨平台使用,配合网页端操作,简直是一代下载神器. 安装 Debian/Ubuntu: ...

  3. Mysql读写分离——主从数据库+Atlas

    mysql集群 最近在参加项目开发微信小程序后台,由于用户数量巨大,且后台程序并不是很完美,所以对用户的体验很是不友好(简单说就是很卡).赶巧最近正在翻阅<大型网站系统与Java中间件实践> ...

  4. wordpress登录密码框明文显示最后一个输入的字符

    wordpress登录密码框明文显示最后一个输入的字符 (function(a){a.fn.dPassword=function(c){var e={interval:200,duration:100 ...

  5. 函数式编程与React高阶组件

    相信不少看过一些框架或者是类库的人都有印象,一个函数叫什么creator或者是什么什么createToFuntion,总是接收一个函数,来返回另一个函数.这是一个高阶函数,它可以接收函数可以当参数,也 ...

  6. LeetCode 566. Reshape the Matrix (C++)

    题目: In MATLAB, there is a very useful function called 'reshape', which can reshape a matrix into a n ...

  7. 第三次博客作业JSF

    JSF规格化设计发展史以及为什么得到人们重视 查阅了n多资料但是仍然没找到. 就说一些jsf的优势吧. 优势:    (1)UI组件 (2)事件驱动模式 (3)用户界面到业务逻辑的直接映射 (4)程序 ...

  8. 2017-2018-2 1723 『Java程序设计』课程 结对编程练习_四则运算

    一.结对对象 姓名:侯泽洋 学号:20172308 担任角色:驾驶员(侯泽洋) 伙伴第一周博客地址 二.本周内容 1.程序需求 (1).自动生成题目 可独立使用(能实现自己编写测试类单独生成题目的功能 ...

  9. 初学Cocos2dx

    初学cocos2dx Cocos2dx 中的主要概念包括:应用.导演.场景.层.精灵.动画.动作. Cocos2dx里面的主要类 1.CCObject Object Object Object 是co ...

  10. AttributeError: module ‘tensorflow.python.ops.nn’ has no attribute ‘leaky_relu’

    #AttributeError: module 'tensorflow.python.ops.nn' has no attribute 'leaky_relu' 的原因主要是版本的问题 解决方法是更新 ...