【uoj125】 NOI2013—书法家
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—书法家的更多相关文章
- BZOJ3241/UOJ125 [Noi2013]书法家
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- [Noi2013]书法家
来自FallDream的博客,未经允许,请勿转载,谢谢. 小E同学非常喜欢书法,他听说NOI2013已经开始了,想题一幅“NOI”的字送给大家. 小E有一张非常神奇的纸,纸可以用一个n 行m 列的二维 ...
- BZOJ 3241: [Noi2013]书法家
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3241 题意: 思路:把每个字母分成三部分,两个字母之间还有空的列,所以我一共设了11个状态 ...
- P1398 [NOI2013]书法家
传送门 就是个普及组 $dp$ 合集,把 $NOI$ 从左到右拆成 $9$ 个部分,每个部分都可以分别 $dp$ 除了 $N$ 的中间部分比较恶心以外其他都还好,自己推一下然后就知道转移,就 $N$ ...
- luogu P1398 [NOI2013]书法家
传送门 注意到\(N\ O\ I\)三个字母都可以从左到右拆成三部分,即\(N=\)一个矩形+一堆矩形+一个矩形,\(O=\)一条+两条横的+一条,\(I=\)两条横的+一个矩形+两条横的,所以可以拆 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- NOI2013 Day2
NOI2013 Day2 矩阵游戏 题目描述:设矩阵\(F\) 求\(F[n][m](mod (10^9+7))\) solution: 这题可以求通项解决. 设\(X_i=F[i][m]\), \( ...
- bzoj 3242: [Noi2013]快餐店 章鱼图
3242: [Noi2013]快餐店 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 266 Solved: 140[Submit][Status] ...
- bzoj 3240: [Noi2013]矩阵游戏 矩阵乘法+十进制快速幂+常数优化
3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 613 Solved: 256[Submit][Status] ...
随机推荐
- static笔记
目录 1. static概括 2. static特点 1. 被static修饰的成员变量属于类,不属于这个类的某个对象. 2.被static修饰的成员可以并且建议通过类名直接访问 3. static注 ...
- Python遗传算法工具箱DEAP框架分析
本文主要介绍python遗传算法工具箱DEAP的实现.先介绍deap的如何使用,再深入介绍deap的框架实现,以及遗传算法的各种实现算法. 代码可以参考 https://github.com/suma ...
- mkdir命令详情
基础命令学习目录首页 原文链接:https://blog.csdn.net/zwlove5280/article/details/74618041 mkdir 是创建目录的命令. 创建一级目录 mkd ...
- caffe 预训练 或者Fine-Tuning 操作
1.使用预训练模型,需要修改训练的prototxt,将layer name改为与要使用模型的layer name相同即可. Borrowing Weights from a Pretrained Ne ...
- Django_csrf
CSRF攻击介绍 CSRF 攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执行在权限保护之下的操作.比如说,受害者 Bob 在银行有一笔存款,通过对银行的 ...
- cnblogs用户体验评价
1. 是否提供良好的体验给用户(同时提供价值)? 博客园就相当于现在生活中处处可见的微博,所有人都在上面发表自己的一些看法,当然我们比较关注的是计算机编程方面的一些博客,大多数编程人员愿意分享自己的代 ...
- SQLyog的基本使用
[简介] SQLyog是mysql数据库的客户端软件 [基本使用] 1.连接mysql数据库 2.SQLyog的页面使用介绍 3.基本的数据库命令 1) use命令 切换数据库 2) unsigned ...
- 关于rand()函数 转载于其他人
C++中的rand()函数 分类: 编程语言/ C#/ 文章 C++中产生随机数种子对于初学者一直都很困惑.大家知道,在C中有专门的srand(N)函数可以轻松实现这一功能,然而在C++中则要复杂一些 ...
- Task 6.3 冲刺Two之站立会议1
今天是二次冲刺的第一天,由于第一阶段已经大概完成了软件的主体功能和框架,我主要看了一下同学们提出的视频和音质的问题,想办法做出了相应的改善.另外我们的功能还是比较单一的,要对主界面进行一定的扩充,所以 ...
- ubuntu16.04+pycharm+默认文件头注释
安装 1.sudo gedit /etc/hosts 2.最后一行添加 0.0.0.0 account.jetbrains.com 3.从 http://idea.lanyus.com/ 中获取激活码 ...