NC20273 [SCOI2009]粉刷匠
题目
题目描述
windy有 N 条木板需要被粉刷。 每条木板被分为 M 个格子。 每个格子要被刷成红色或蓝色。
windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。
如果windy只能粉刷 T 次,他最多能正确粉刷多少格子?
一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。
输入描述
输入文件paint.in第一行包含三个整数,N M T。
接下来有N行,每行一个长度为M的字符串,'0'表示红色,'1'表示蓝色。
输出描述
输出文件paint.out包含一个整数,最多能正确粉刷的格子数。
示例1
输入
3 6 3
111111
000000
001100
输出
16
备注
30%的数据,满足 \(1 \le N,M \le 10 ;0 \le T \le 100\) 。
100%的数据,满足 \(1 \le N,M \le 50 ; 0 \le T \le 2500\) 。
题解
方法一
知识点:线性dp。
这道题相当于 \(k\) 串最大和套 \(k\) 串最大和,十分巧妙。
首先考虑设 \(f[i][j]\) 为考虑到第 \(i\) 行,共连续刷了 \(j\) 次的最多刷对格数。发现转移时的累加和变为第 \(i\) 行,考虑到第 \(m\) 格,共刷了 \(k\) 次的最多刷对格数,用 \(g[i][m][k]\) 表示。有转移方程为:
\]
接下来考虑求 \(g[i][j][k]\) ,每行是独立的,第一维可以不考虑。接下来就和 \(k\) 串最大和一致,有转移方程:
\]
其中 \(sum[i][j]\) 代表第 \(i\) 行前 \(j\) 个数里 \(1\) 的数量,\(\max (s,l-s)\) 表示新刷的 \([j-l+1,j]\) 里刷数量最多的种类。
时间复杂度 \(O(nm^2t +nt^2)\)
空间复杂度 \(O(nmt)\)
方法二
知识点:线性dp。
思路差不多,就是状态设置不一样,设 \(f[i][j][k][l]\) 表示为在 \((i,j)\) 处的格子,已经刷了 \(k\) 次,这个格子状态为 \(l\) (0/1,涂0/涂1)。显然有转移方程:
\begin{array}{l}
f[i][j][k][0] = \max(f[i][j-1][k-1][0],f[i][j-1][k-1][1]) + [a[i][j] = 0] &,j = 1\\
f[i][j][k][1] = \max(f[i][j-1][k-1][0],f[i][j-1][k-1][0]) + [a[i][j] = 1] &,j = 1\\
f[i][j][k][0] = \max(f[i][j-1][k][0],f[i][j-1][k-1][1]) + [a[i][j] = 0] &,j \neq 1\\
f[i][j][k][1] = \max(f[i][j-1][k-1][0],f[i][j-1][k][0]) + [a[i][j] = 1] &,j \neq 1
\end{array}
\right.
\]
\(j = 1\) ,必须换行,即必须分段。
时间复杂度 \(O(nmt)\)
空间复杂度 \(O(nmt)\)
代码
方法一
#include <bits/stdc++.h>
using namespace std;
int sum[57][57], f[57][2507], g[57][57][2507];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m, t;
cin >> n >> m >> t;
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= m;j++) {
char x;
cin >> x;
sum[i][j] = sum[i][j - 1];
if (x == '1') sum[i][j]++;
}
}
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
for (int k = 1;k <= t;k++)
for (int l = 1;l <= j;l++)
g[i][j][k] = max(g[i][j][k], g[i][j - l][k - 1] + max(sum[i][j] - sum[i][j - l], l - (sum[i][j] - sum[i][j - l])));
for (int i = 1;i <= n;i++)
for (int j = 1;j <= t;j++)
for (int k = 1;k <= j;k++)
f[i][j] = max(f[i][j], f[i - 1][j - k] + g[i][m][k]);
cout << f[n][t] << '\n';
return 0;
}
方法二
#include <bits/stdc++.h>
using namespace std;
int a[57][57], f[57][57][2507][2];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m, t;
cin >> n >> m >> t;
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= m;j++) {
char x;
cin >> x;
a[i][j] = x - '0';
}
}
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= m;j++) {
for (int k = 1;k <= t;k++) {
if (j == 1) {
f[i][j][k][0] = max(f[i - 1][m][k - 1][1], f[i - 1][m][k - 1][0]) + (a[i][j] == 0);
f[i][j][k][1] = max(f[i - 1][m][k - 1][1], f[i - 1][m][k - 1][0]) + (a[i][j] == 1);
}
else {
f[i][j][k][0] = max(f[i][j - 1][k][0], f[i][j - 1][k - 1][1]) + (a[i][j] == 0);
f[i][j][k][1] = max(f[i][j - 1][k - 1][0], f[i][j - 1][k][1]) + (a[i][j] == 1);
}
}
}
}
cout << max(f[n][m][t][0], f[n][m][t][1]) << '\n';
return 0;
}
NC20273 [SCOI2009]粉刷匠的更多相关文章
- BZOJ 1296: [SCOI2009]粉刷匠 分组DP
1296: [SCOI2009]粉刷匠 Description windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上 ...
- BZOJ 1296: [SCOI2009]粉刷匠( dp )
dp[ i ][ j ] = max( dp[ i - 1 ][ k ] + w[ i ][ j - k ] ) ( 0 <= k <= j ) 表示前 i 行用了 j 次粉刷的机会能正 ...
- 【BZOJ1296】[SCOI2009]粉刷匠(动态规划)
[BZOJ1296][SCOI2009]粉刷匠(动态规划) 题面 BZOJ 洛谷 题解 一眼题吧. 对于每个串做一次\(dp\),求出这个串刷若干次次能够达到的最大值,然后背包合并所有的结果即可. # ...
- 1296: [SCOI2009]粉刷匠[多重dp]
1296: [SCOI2009]粉刷匠 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1919 Solved: 1099[Submit][Statu ...
- 【BZOJ1296】[SCOI2009]粉刷匠 (DP+背包)
[SCOI2009]粉刷匠 题目描述 \(windy\)有 \(N\) 条木板需要被粉刷. 每条木板被分为 \(M\) 个格子. 每个格子要被刷成红色或蓝色. \(windy\)每次粉刷,只能选择一条 ...
- 背包 DP【洛谷P4158】 [SCOI2009]粉刷匠
P4158 [SCOI2009]粉刷匠 windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上 ...
- BZOJ_1296_[SCOI2009]粉刷匠_DP
BZOJ_1296_[SCOI2009]粉刷匠_DP Description windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能 ...
- [Bzoj1296][Scoi2009] 粉刷匠 [DP + 分组背包]
1296: [SCOI2009]粉刷匠 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2184 Solved: 1259[Submit][Statu ...
- bzoj1296: [SCOI2009]粉刷匠(DP)
1296: [SCOI2009]粉刷匠 题目:传送门 题解: DP新姿势:dp套dp 我们先单独处理每个串,然后再放到全局更新: f[i][k]表示当前串枚举到第i个位置,用了k次机会 F[i][j] ...
随机推荐
- 面试官:Dubbo怎么实现服务降级,他有什么好处?
哈喽!大家好,我是小奇,一位热爱分享的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 书接上回,今天周一了,招聘软件 ...
- prop传值
将FooterMusic.vue中的play方法转到MusicDetail.vue中 用" :"v-bind 指令可以用于响应式地更新 HTML 特性:,在此进行动态赋值(play ...
- JavaScript之创建八个对象过520
马上又到了一年一度的520了,程序猿们赶紧创建对象过520吧!!! JavaScript创建对象的几种方式: 一:字面量方式: var obj = {name: '程序猿'}; 二:通过new操作符: ...
- 实验一:在FW上配置静态路由实现互通
实验:在FW上配置静态路由实现互通 网络拓扑图 一.配置步骤 1.配置IP地址 R1: FW: ISP: 2.配置路由 ①在R2上面配置静态路由 ②在ISP上面配置静态路由 3.在FW上配 ...
- VR技术赋能五大领域,不止高级,更高效!
除了VR游戏.VR影视作品,究竟还有哪些产业领域会应用到VR技术并为生活带来改变呢?今天就帮大家好好梳理一下~ VR赋能交通,不只是高级 最近在网上看到了VR考驾照的新闻,网友都赞叹,现在学车都这么高 ...
- python 连接SAP 代码
def Main(): sap_app = r"C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe" subproces ...
- SAP 实例 4 CFW
*&---------------------------------------------------------------------* *& Report demo_cfw ...
- Linux文件查找实现
文件查找 locate:非实时查找(依赖数据库的方式) find(实时查找) locate:-- 模糊搜索(不适合经常改变的文件) locate 查询系统上预建的文件索引数据库 /var/lib/ml ...
- Linux 批量杀死进程(详细版本)
使用场景 当程序中有使用到多进程且进程数较多的情况,如下图,且需要通过控制台杀死所有的 GSM_run.py 的进程时,利用 kill 命令一个一个的去结束进程是及其耗时且繁琐的,这时就需要我们的ki ...
- [ 1 x 1 ] Convolution-1*1卷积的作用
一.卷积神经网络中的卷积(Convolution in a convoluted neural network) 具体内容亲参考<深度学习>. 二.1*1卷积(one by one con ...