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. Hyperledger Fabric CA User’s Guide——配置设置(四)

    配置设置 Fabric CA提供了三种方案去配置Fabric CA服务端和客户端,优先顺序是: CLI flags(标识) 环境变量 配置文件 在本文档的其余部分中,我们将对配置文件进行更改.但是,可 ...

  2. c++ 整数和字符串的转化

    一.string转int的方式 采用最原始的string, 然后按照十进制的特点进行算术运算得到int,但是这种方式太麻烦,这里不介绍了. 采用标准库中atoi函数. "; int a = ...

  3. js备忘录4

    for (var key in obj) { console.log('对象属性名:' , key); if (obj[key] instanceof Object) { sayName(obj[ke ...

  4. Linux安装软件包

    今天在坐公交的路上看到一遍文章感觉还不错,先收集了.原文链接 Linux安装软件包

  5. MathExam6317

    自己取一个大气又可爱的标题 小学二年级的还没来得及写,大部分时间还是花在巩固和查阅新旧知识上了,通过看学习视频,查资料,看博客园的博客...下次完善好了交上. 一.预估与实际 PSP2.1 Perso ...

  6. 【请仔细核对Git地址】关于代码量排名的说明

    1.截至2017年3月14日,1623班级代码统计情况如下: 2.代码量排名是基于码云的git地址统计的,请大家仔细核对以下个人地址,如有问题请及时联系我. 20162301 20162302 201 ...

  7. 20162327WJH第一次实验——线性结构

    20162327WJH第一次实验--线性结构 实 验 报 告 实 验 报 告 课程:程序设计与数据结构 班级: 1623 姓名: 王旌含 学号:20162327 成绩: 2分 指导教师:娄嘉鹏 王志强 ...

  8. 第二阶段Sprint冲刺会议6

    进展:将“录制”及“保存”整合到一起,修复出现的Bug,使之能够正常运行.

  9. 团队作业4——第一次项目冲刺(Alpha版本)2017.11.16

    1.当天站立式会议照片 本次会议在5号公寓3楼召开,本次会议内容:①:熟悉每个人想做的模块.②:根据老师的要求将项目划分成一系列小任务.③:在上次会议内容完成的基础上增加新的任务. 2.每个人的工作 ...

  10. 深入理解Java类加载器(2)

    1 基本信息 每个开发人员对Java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这背后就涉及到了java技术体系中的类加载.Java的类加载机制是技术体系中比较核心的 ...