LOJ#2668 书法家
题意:要在一张网格纸上画出NOI图形,使得所占格子的权值和最大。
解:暴力DP即可...
从左往右,每个字母都可以被划分成三块,且每块都可用上下两维来表示。
于是一块一块的DP。考虑如何O(1)转移。显然只有N的中间那一块不好转移,别的都是直接转移。
N的三块的两个连接处之间,可以枚举必须持平的那个端点,另一个用前缀最值。
N第二块内部,考虑枚举后一个矩形的上边界,逐步扩展下边界。此时发现每扩展一步,可能的决策集合会增加:左边一格,下边界为刚扩展的那一格,上边界在枚举的上边界以上的所有状态。
于是对于每个下边界,预处理出上边界从上到下的一个前缀最值,加到决策集合里取max即可。
#include <bits/stdc++.h> const int INF = 0x3f3f3f3f; #define g f[FLAG]
#define h f[FLAG ^ 1] int f[][][][], FLAG, n, m;
int s[][], p[], temp[][]; inline int getSum(int i, int l, int r) {
if(l > r) return ;
return s[r][i] - s[l - ][i];
} inline void out() {
for(int i = ; i <= m; i++) {
for(int up = ; up <= n; up++) {
for(int down = up; down <= n; down++) {
printf("%d ", g[i][up][down]);
}
}
puts("");
}
puts("");
return;
} inline void outp() {
printf("p : ");
for(int i = ; i <= m; i++) {
printf("%d ", p[i]);
}
puts("");
puts("");
return;
} int main() {
//printf("%d \n", sizeof(f) / 1048576); scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) {
for(int j = ; j <= m; j++) {
scanf("%d", &s[i][j]);
s[i][j] += s[i - ][j];
}
} FLAG = ; /// N 1
memset(g, ~0x3f, sizeof(g));
for(int i = ; i <= m; i++) {
for(int up = ; up < n; up++) {
for(int down = up + ; down <= n; down++) {
g[i][up][down] = std::max(, g[i - ][up][down]) + getSum(i, up, down);
}
}
} //out(); FLAG ^= ; /// N 1.5
memset(g, ~0x3f, sizeof(g));
for(int i = ; i <= m; i++) {
for(int up = ; up < n; up++) {
int large = -INF;
for(int down = n - ; down >= up; down--) {
large = std::max(large, h[i - ][up][down + ]);
g[i][up][down] = large + getSum(i, up, down);
}
}
} //out(); FLAG ^= ; /// N 2
//memset(g, ~0x3f, sizeof(g));
memcpy(g, h, sizeof(h));
for(int i = ; i <= m; i++) {
memset(temp, ~0x3f, sizeof(temp));
for(int down = ; down <= n; down++) {
for(int up = ; up <= down; up++) {
temp[down][up] = std::max(temp[down][up - ], std::max(g[i - ][up][down], h[i - ][up][down]));
}
}
for(int up = ; up <= n; up++) {
int large = temp[up - ][up - ];
for(int down = up; down <= n; down++) {
large = std::max(large, temp[down][up]);
g[i][up][down] = std::max(large + getSum(i, up, down), h[i][up][down]);
}
}
} //out(); FLAG ^= ; /// N 2.5
memset(g, ~0x3f, sizeof(g));
for(int i = ; i <= m; i++) {
for(int down = ; down <= n; down++) {
int large = -INF;
for(int up = down - ; up >= ; up--) {
large = std::max(large, h[i - ][up + ][down]);
g[i][up][down] = large + getSum(i, up, down);
}
}
} //out(); FLAG ^= ; /// N 3
memset(g, ~0x3f, sizeof(g));
for(int i = ; i <= m; i++) {
for(int up = ; up < n; up++) {
for(int down = up + ; down <= n; down++) {
g[i][up][down] = std::max(h[i][up][down], g[i - ][up][down] + getSum(i, up, down));
}
}
} //out(); /// get p : max of g
memset(p, ~0x3f, sizeof(p));
for(int i = ; i <= m; i++) {
p[i] = p[i - ];
for(int up = ; up <= n; up++) {
for(int down = ; down <= n; down++) {
p[i] = std::max(p[i], g[i][up][down]);
}
}
} //outp(); //out(); //printf(" O 1 \n"); FLAG ^= ; /// O 1
memset(g, ~0x3f, sizeof(g));
for(int i = ; i <= m; i++) {
for(int up = ; up < n - ; up++) {
for(int down = up + ; down <= n; down++) {
g[i][up][down] = p[i - ] + getSum(i, up, down);
}
}
} //out(); //printf(" O 2 \n"); FLAG ^= ; /// O 2
memset(g, ~0x3f, sizeof(g));
for(int i = ; i <= m; i++) {
for(int up = ; up < n - ; up++) {
for(int down = up + ; down <= n; down++) {
g[i][up][down] = std::max(h[i - ][up][down], g[i - ][up][down]) + getSum(i, up, up) + getSum(i, down, down);
}
}
} //out(); FLAG ^= ; /// O 3
memset(g, ~0x3f, sizeof(g));
for(int i = ; i <= m; i++) {
for(int up = ; up < n - ; up++) {
for(int down = up + ; down <= n; down++) {
g[i][up][down] = h[i - ][up][down] + getSum(i, up, down);
}
}
} //out(); /// get p : max of g
memset(p, ~0x3f, sizeof(p));
for(int i = ; i <= m; i++) {
p[i] = p[i - ];
for(int up = ; up < n - ; up++) {
for(int down = up + ; down <= n; down++) {
p[i] = std::max(p[i], g[i][up][down]);
}
}
} //outp(); //out(); FLAG ^= ; /// I 1
memset(g, ~0x3f, sizeof(g));
for(int i = ; i <= m; i++) {
for(int up = ; up < n - ; up++) {
for(int down = up + ; down <= n; down++) {
g[i][up][down] = std::max(p[i - ], g[i - ][up][down]) + getSum(i, up, up) + getSum(i, down, down);
}
}
} //out(); FLAG ^= ; /// I 2
memset(g, ~0x3f, sizeof(g));
for(int i = ; i <= m; i++) {
for(int up = ; up < n - ; up++) {
for(int down = up + ; down <= n; down++) {
g[i][up][down] = std::max(g[i - ][up][down], h[i - ][up][down]) + getSum(i, up, down);
}
}
} //out();
int ans = -INF; FLAG ^= ; /// I 3
memset(g, ~0x3f, sizeof(g));
for(int i = ; i <= m; i++) {
for(int up = ; up < n - ; up++) {
for(int down = up + ; down <= n; down++) {
g[i][up][down] = std::max(g[i - ][up][down], h[i - ][up][down]) + getSum(i, up, up) + getSum(i, down, down);
ans = std::max(g[i][up][down], ans);
}
}
} //out(); printf("%d\n", ans);
return ;
}
AC代码
LOJ#2668 书法家的更多相关文章
- BZOJ 2668 交换棋子(费用流)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2668 题意:有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子中的棋子,最终达到目标状 ...
- 【BZOJ】【2668】【CQOI2012】交换棋子
网络流/费用流 跪跪跪,居然还可以这样建图…… 题解:http://www.cnblogs.com/zig-zag/archive/2013/04/21/3033485.html 考虑每个点的交换限制 ...
- [Noi2016]区间 BZOJ4653 洛谷P1712 Loj#2086
额... 首先,看到这道题,第一想法就是二分答案+线段树... 兴高采烈的认为我一定能AC,之后发现n是500000... nlog^2=80%,亲测可过... 由于答案是求满足题意的最大长度-最小长 ...
- Loj #2192. 「SHOI2014」概率充电器
Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...
- Loj #3096. 「SNOI2019」数论
Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...
- Loj #3093. 「BJOI2019」光线
Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...
- Loj #3089. 「BJOI2019」奥术神杖
Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...
- Loj #2542. 「PKUWC2018」随机游走
Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...
- Loj #2331. 「清华集训 2017」某位歌姬的故事
Loj #2331. 「清华集训 2017」某位歌姬的故事 IA 是一名会唱歌的女孩子. IOI2018 就要来了,IA 决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符, ...
随机推荐
- sql 服务启动失败 SQL Server(MSSQLSERVER) 错误码126
SQL配置管理器-->sql server 网络配置-->mssqlerver的协议-->VIA禁用服务
- async await详解
async await本身就是promise + generator的语法糖. 本文主要讲述以下内容 async awiat 实质 async await 主要特性 async await 实质 下面 ...
- Windows下建立ArcGIS Server集群
原创文章,转载须标明出处自: http://www.cnblogs.com/gisspace/p/8269525.html -------------------------------------- ...
- node.js微信小程序配置消息推送
在开发微信小程序时,有一个消息推送,它的解释是这样的. 消息推送具体的内容是下面的这个网址 https://developers.weixin.qq.com/miniprogram/dev/fra ...
- java笔记---- 获取外网(公网)的ip地址
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import ...
- C语言面试基础知识整理
一.预处理 1.什么是预编译?何时需要预编译? (1)预编译又称预处理,是做些代码文本的替换工作,即程序执行前的一些预处理工作.主要处理#开头的指令,如拷贝#include包含的文件代码.替换#def ...
- WPF C# 命令的运行机制
1.概述 1.1 WPF C# 命令的本质 命令是 WPF 中的输入机制,它提供的输入处理比设备输入具有更高的语义级别. 例如,在许多应用程序中都能找到的“复制”.“剪切”和“粘贴”操作就是命令. W ...
- 数据库MySQL和Redis实践
1.关于数据库设计的那些事 2.MySQL 3.Redis
- 第一课android开发之在activity间传递参数
一.活动间简单参数传递:1.在布局中添加按钮,用<Button,用id设置id名称,id="@+id/这儿填写你要设置成的名称":用text设置按钮上显示的文字.text=& ...
- 下载带有kali linux系统的VMware如何打开虚拟机?
下载带有kali linux系统的VMware如何打开虚拟机? 一.安装VMware 温馨提示:如果你对虚拟机一无所知的话,最好不要自己下载kali linux系统的ISO镜像和VMware虚拟机,然 ...