本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!

Description

小E同学非常喜欢书法,他听说NOI2013已经开始了,想题一幅“NOI”的字送给大家。

小E有一张非常神奇的纸,纸可以用一个n 行m 列的二维方格矩阵来表示,为了描述方便,我们定义矩阵左下角方格坐标为(1,1) ,右上角方格坐标为(m,n) 。矩阵的每个方格有一个整数的幸运值。在格子上面写字可以增加大家的幸运度,幸运度的大小恰好是所有被笔写到的方格的幸运值之和。现在你要在上面写上 ‘N’,‘O’,‘I’三个字母。

下面给出3个书法字的定义:

1.‘N’由若干(≥3)个边平行于坐标轴的矩形组成,设有K个矩形组成(标号1~K),第i个矩形的左下角方格坐标设为(Li ,Bi) ,右上角坐标设为(Ri ,Ti) ,要求满足:
a)Li<=Ri,Bi<=Ti
b)对任意1<i<=K,有Li=R(i-1)+1
c)对任意3<=i<K,有B(i-1)-1<=Ti<=T(i-1),Bi<=B(i-1);" 
d)B2>B1,T2=T1,B(K-1)=B(K),T(k-1)<T(K)

2.‘O’由一个大矩形A,挖去一个小矩形B得到,这两个矩形的边都平行于坐标轴。设大矩形左下角的方格坐标为(u,v),长为W宽为H,则小矩形B满足左下角方格坐标为(u+1,v+1) ,长W-2 ,宽H-2。要求满足:
a)W>=3,H>=3
b)u>R(K)+1

3.‘I’为3个边平行于坐标轴的从下到上的实心矩形组成,从下到上依次标号为1,2,3,第i 个矩形的左下角格子坐标设为(Pi , Qi ),右上角格子坐标设为(Gi , Hi ),要求满足:
a)Pi<=Gi,Qi<=Hi
b)P1=P3>u+W,G1=G3
c)Q1=H1=Q2-1,H2+1=Q3=H3
d)P1<P2<=G2<G1

下图是一个‘N’,‘O’,‘I’的例子

另外,所有画的图形均不允许超过纸张的边界。现在小E想要知道,他能画出的最大幸运度是多少。

Input

第一行包含两个正整数n和m,分别表示矩阵的行数和列数。
接下来n行,每行有m个整数,第i+1行的第j个数表示格子(j,n-i+1)的幸运值。

Output

输出一个整数T,表示小E能够获得的最大幸运度

Sample Input

【样例输入1】
3 13
1 1 -1 -1 1 -1 1 1 1 -1 1 1 1
1 -1 1 -1 1 -1 1 -1 1 -1 -1 1 -1
1 -1 -1 1 1 -1 1 1 1 -1 1 1 1

【样例输入2】
3 13
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1

Sample Output

【样例输出1】
24
【样例输出2】
-20

HINT

正解:DP

解题报告:

  复述一遍要求:

  “N”由三个部分组成:最左边是一个矩形,最右边也是一个矩形,中间部分是若干个矩形,要求横坐标必须连续,同时左下、右上纵坐标不升,并且第一个矩形与最左边的上端齐平,最后一个矩形与最右边的下端齐平。

  “O”必须是一个矩形挖掉了中间,得到的一个宽度只能为1的边框。

  “I”只能是上下两个高为1的全等矩形中间夹一个任意形状的矩形(左右边界必须被严格限制在范围内)。

  三个字母中间需要至少隔开一列。

  别的转移都很好做,就是基础DP。唯独N的中间的转移需要仔细考虑。

  分为从1转来和从2转来两种,首先从1转来的话,只需要从n for到1,固定上界的同时保存后缀最大值,更新即可。

  从2转来的话,预处理一下前缀最大值,即下界固定为j,上界为1到i中的最大值。

  更新的时候,让j从i for到n,直接更新即可。

  最后补充一点就是,只能在9处更新答案,空格可以用两个变量存着。

  细节很多,需要仔细调试...

//It is made by ljh2000
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <complex>
using namespace std;
typedef long long LL;
const int MAXN = 152;
const int MAXM = 520;
const int inf = (1<<30)-1;
int n,m,xing[MAXN][MAXM],dp[MAXN][MAXN],ans;
int f[2][12][MAXN][MAXN],s[MAXN],blank[MAXM][2];
//f[0、1][type][i][j] inline int getint(){
int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
} inline void upd(int &x,int y){ if(x<y) x=y; } inline void work(){
n=getint(); m=getint(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) xing[i][j]=getint();
int tag=1,last,now; ans=-inf; for(int i=0;i<=m;i++) blank[i][0]=blank[i][1]=-inf;
memset(f,-0x3f,sizeof(f));
for(int lie=1;lie<=m;lie++) {//枚举列
last=tag; tag^=1; blank[lie][0]=blank[lie-1][0]; blank[lie][1]=blank[lie-1][1];
memset(f[tag],-0x3f,sizeof(f[tag]));
s[0]=0; for(int i=1;i<=n;i++) s[i]=s[i-1]+xing[i][lie];//前缀和
//1:the left of N
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++) {
upd(f[tag][1][i][j],s[j]-s[i-1]);
upd(f[tag][1][i][j],f[last][1][i][j]+s[j]-s[i-1]);
} //2:the middle of N
memset(dp,-0x3f,sizeof(dp));
for(int j=1;j<=n;j++) for(int i=1;i<=j;i++) dp[i][j]=max(dp[i-1][j],f[last][2][i][j]);//前缀最大值(下界为j),即下界固定为j,上界为1到i中的最大值
for(int i=1;i<=n;i++) {//这一次上界i,下界为j
now=dp[i-1][i-1];//上一次的下界取值最小要为i-1
//和2相接
for(int j=i;j<=n;j++){//枚举下界
upd(now,dp[i][j]);
upd(f[tag][2][i][j],now);
}
//和1相接
now=-inf;//后缀最大值
for(int j=n;j>=i;j--) {
//now保存的是上界为i,下界为j+1到n的矩阵中的1的最大值
upd(now,f[last][1][i][j+1]);//1和2相接的地方,必须要间隔1。一路往上取max即可
upd(f[tag][2][i][j],now);
}
for(int j=i;j<=n;j++) f[tag][2][i][j]+=s[j]-s[i-1];
} //3:the right of N
for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) dp[i][j]=f[last][2][i][j];
for(int j=1;j<=n;j++) for(int i=j;i>=1;i--) upd(dp[i-1][j],dp[i][j]);//后缀max
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++) {
upd(f[tag][3][i][j],dp[i+1][j]+s[j]-s[i-1]);
upd(f[tag][3][i][j],f[last][3][i][j]+s[j]-s[i-1]);
} //N和O中间的空行
for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) upd(blank[lie][0],f[last][3][i][j]); //4:the left of O
for(int i=1;i<=n;i++)
for(int j=i+2;j<=n;j++)
f[tag][4][i][j]=blank[lie-1][0]+s[j]-s[i-1]; //5:the middle of O
for(int i=1;i<=n;i++)
for(int j=i+2;j<=n;j++)
f[tag][5][i][j]=max(f[last][5][i][j],f[last][4][i][j])+xing[i][lie]+xing[j][lie]; //6:the right of O
for(int i=1;i<=n;i++)
for(int j=i+2;j<=n;j++)
f[tag][6][i][j]=f[last][5][i][j]+s[j]-s[i-1]; //O和I中间的空行
for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) upd(blank[lie][1],f[last][6][i][j]); //7:the left of I
for(int i=1;i<=n;i++)
for(int j=i+2;j<=n;j++)
f[tag][7][i][j]=max(f[last][7][i][j],blank[lie-1][1])+xing[i][lie]+xing[j][lie]; //8:the middle of I
for(int i=1;i<=n;i++)
for(int j=i+2;j<=n;j++)
f[tag][8][i][j]=max(f[last][8][i][j],f[last][7][i][j])+s[j]-s[i-1]; //9:the right of I
for(int i=1;i<=n;i++)
for(int j=i+2;j<=n;j++)
f[tag][9][i][j]=max(f[last][8][i][j],f[last][9][i][j])+xing[i][lie]+xing[j][lie],ans=max(ans,f[tag][9][i][j]);
}
printf("%d",ans);
} int main()
{
work();
return 0;
}

  

BZOJ3241/UOJ125 [Noi2013]书法家的更多相关文章

  1. 【uoj125】 NOI2013—书法家

    http://uoj.ac/problem/125 (题目链接) 题意 在网格上写“NOI”,每个格子上有一些权值,要求覆盖的权值最大.书写有一些规则. Solution 将“NOI”分成11个部分, ...

  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. oracle clob字段去除html标签

    通过正则表达式的方式去除html标签 select regexp_replace(content,'</?[^>]*>|nbsp;|&','') content from T ...

  2. 通知url必须为直接可访问的url,不能携带参数 异步接收微信支付结果通知的回调地址 不能携带参数。 回调地址后是否可以加自定义参数 同步回调地址 异步回调地址 return_url和notify_url的区别

    [微信支付]微信小程序支付开发者文档 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7 通知url必须为直接可访问的 ...

  3. /cloudmonitor.log 主机监控

    989866842 INFO 2018-09-30 01:38:58.58 [ricGatherServiceHttp] 提交指标完成,耗时:18ms. SystemInfo [serialNumbe ...

  4. Cookies with curl the command line tool

    w https://curl.haxx.se/docs/http-cookies.html curl has a full cookie "engine" built in. If ...

  5. FW ImageMagick

    ExploitFixes ImageMagick < 6.9.3-9 - Multiple Vulnerabilities 2016-05-04 22:05:53 Nikolay Ermishk ...

  6. Android系统移植与调试之------->如何使用PhotoShop转换24位的bmp图片为16位bmp图片

    使用Android移植时候,很多图片都需要16为的bmp格式,所以研究了一下如何从24位转换成16位,供大家参阅 step1:查看bmp图片的属性,如下图所示,是24位的 step2:用PhotoSh ...

  7. hadoop学习(一)概念理解

    1.概念 1.1什么是hadoop? hadoop 是大数据存储和处理的框架,主要组成为文件存储系统hdfs和分布式计算框架mapreduce. 1.2能做什么,擅长做什么,不擅长做什么? 1.2.1 ...

  8. django路由系统之反向生成url

    from niubin.service import v1 from django.urls import reverse from django.shortcuts import HttpRespo ...

  9. "深入理解C语言" 指针

    本文对coolshell中的"深入理解C语言"这篇文章中提到的指针问题, 进行简要的分析. #include <stdio.h> int main(void){ ]; ...

  10. ionic项目注意点

    1.controller 名字一定要大写 config如过传递controller,则要使用controllerAs ,开头使用小写 2.在scss中新添加scss文件,要重启