题目链接

题目

题目描述

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]\) 表示。有转移方程为:

\[f[i][j] = \max (f[i-1][j],f[i-1][j-k] + g[i][m][k]),1 \leq k \leq j
\]

接下来考虑求 \(g[i][j][k]\) ,每行是独立的,第一维可以不考虑。接下来就和 \(k\) 串最大和一致,有转移方程:

\[g[i][j][k] = \max (g[i][j-1][k],g[i][j-l][k-1] + \max(s,l - s)),s = sum[i][j] - sum[i][j-l] ,1 \leq l \leq j
\]

其中 \(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)。显然有转移方程:

\[\left \{
\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;
}

最新文章

  1. 使用原生ajax处理json字符串
  2. oracle数据库从入门到精通之三
  3. TestNG参数化测试【转】
  4. 【BZOJ-1046】上升序列 DP + 贪心
  5. POJ3057 Evacuation(二分图最大匹配)
  6. Linux Kconfig及Makefile学习
  7. web.xml里&lt;filter-mapping&gt;中的&lt;dispatcher&gt;作用
  8. 【转】Android的onCreateOptionsMenu()创建菜单Menu详解
  9. mysql学习3
  10. Owin 自寄宿 asp.net web api
  11. Linux内核笔记:epoll实现原理(二)
  12. 访问win10的远程桌面(Remote Desktop)总是凭据或者用户密码错误
  13. WRI$_ADV_OBJECTS表过大,导致PDB的SYSAUX表空间不足
  14. [转载]图解程序员必须掌握的Java常用8大排序算法
  15. java 方法引用(method reference)
  16. 设置UINavigationController标题的属性
  17. 【Java面试题】22 JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?
  18. 终端运行apk
  19. SDUTOJ 2772 KMP简单应用
  20. Celery-4.1 用户指南: Security (安全)

热门文章

  1. 一文学完Linux Shell编程,比书都好懂
  2. Go中rune类型浅析
  3. AcWing 4378. 选取数对
  4. 《HALCON数字图像处理》第三章笔记
  5. NPM Error:gyp: No Xcode or CLT version detected!
  6. HMS Core 视频编辑服务开放模板能力,助力用户一键Get同款酷炫视频
  7. 【Java面试】数据库连接池有什么用?它有哪些关键参数?
  8. 掘地三尺搞定 Redis 与 MySQL 数据一致性问题
  9. 【.NET 6】多线程的几种打开方式和代码演示
  10. ffmpeg使用总结