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. GitHub笔记(三)——分支管理和多人协作

    三.分支管理 0 语句: 查看分支:git branch 创建分支:git branch <name> 切换分支:git checkout <name> 创建+切换分支:git ...

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

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

  3. XSS跨站脚本

    1.反射型 非持久化,需要用户自己点击才可以触发 通常出现在搜索框 <?php $id=$_GET['id']; echo $id; ?> http://127.0.0.1/test/sc ...

  4. (xampp)lampp 下配置https(ssl)自签双向认证以后 apache无法启动解决方案

    自签CA一般是没有应用场景的,因为需要客户端浏览器导入证书才能访问 但是在某些需要内部使用的场景下,确实是一个解决方案 但是在lampp配置了双向认证以后发现 原来自带的管理命令 lampp star ...

  5. 转载---LIBRARY_PATH和LD_LIBRARY_PATH环境变量的区别

    总是分不太清楚LIBRARY_PATH和LD_LIBRARY_PATH环境变量的区别,每次都是现查一下,转载到这里,备忘... 转载自:https://www.cnblogs.com/panfeng4 ...

  6. Python基础_可迭代的/迭代器/生成器

    介绍 可迭代的:内部实现了__iter__方法 迭代器:内部实现了__iter__,__next__方法 生成器:yield,yield from 使用 __iter__() __next__() _ ...

  7. 模块-Memcached、Redis

    目录 Mecache 安装 使用 Redis 安装 Python操作Redis 操作模式 连接池 操作 String Hash List Set sort set 其他常用操作 管道 发布订阅 sen ...

  8. 第十周psp作业

    本周psp 本周进度条 代码累积折线图 博文字数累积折线图 饼状图

  9. OO学习第一阶段总结

    前言 虽然之前接触过java,也写过一些1000行左右的程序.可以说面向对象的思想和java的一些基本语法对我来说是没有难度的,但是这学期的面向对象依然给了我一个下马威.这几次的作业每次都很让我头疼. ...

  10. 1001 A+B

    代码链接 PDF链接 首先要说的是这道题的难点是如何把数字输出加入逗号,毕竟数据范围并没有超过Long.当然这个难点也不是问题,将数字转为字符串,C中就有这样的函数,然后再用 %3==0 这样来控制输 ...