首页 > 其他分享 >[题解] [洛谷P4158] 粉刷匠

[题解] [洛谷P4158] 粉刷匠

时间:2024-04-26 16:35:02浏览次数:25  
标签:include 洛谷 木板 格子 int 题解 粉刷 MAXN P4158

[题解] [洛谷P4158] 粉刷匠

题目描述

有 \(n\) 个木板,每个木板有 \(m\) 个格子,所有格子最开始视为没有颜色。

有 \(0/1\) 两种颜色,每次可以粉刷其中一块木板上一段连续的格子,总共可以粉刷 \(t\) 次。

给出一组目标颜色,问最多可以将多少个格子粉刷成目标颜色。

输入格式

第一行包含三个整数, \(n,m,t(1 \leq n,m \leq 10, 0 \leq t \leq 100)\)

接下来 \(n\) 行,每行一个长度为 \(m\) 的 \(0/1\) 字符串,表示木板颜色

输出格式

包含一个整数,表示能正确粉刷的最多格子数。

题解

为了更直观的求解,本题可以拆分为两个子问题:求第 \(i\) 个木板粉刷 \(j\) 次能够粉刷的最多格子数 \(b_{i,j}\) ,再利用得到的答案求解用前 \(i\) 个木板粉刷 \(j\) 次能够粉刷的最多格子数。

先看第一个子问题,设计状态 \(f_{i,j,k,(0/1)}\) 表示第 \(i\) 个木板的前 \(j\) 个方块粉刷 \(k\) 次,且当前方块粉刷成 \(0/1\) 状态的最大格子数。因为对于每一个格子来说,我们是否需要多消耗一次粉刷次数只取决于粉刷它的上一个格子的时候是否用了和它一样的颜色。假设当前格子颜色是 \(c\) ,可以得到状态转移方程: \(f_{i,j,k,c} = max(f_{i,j-1,k,c} + 1, f_{i,j-1,k-1,!c} + 1)\) 与 \(f_{i,j,k,!c} = max(f_{i,j-1,k,!c}, f_{i,j-1,k-1,c})\)即在是否选择新粉刷一次中选一个更优状态。

第二个子问题就比较简单了,设计状态 \(dp_{i,j} = max(f_{i,m,k} + dp_{i-1,j-k})\) 其中 \(dp_{i,j}\) 表示前 \(i\) 个木板粉刷 \(j\) 次的最大格子数, \(k\) 是在第 \(i\) 个木板粉刷的次数。枚举 \(k\) 转移即可。

AC 代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <stack>
using namespace std;

const int MAXN = 53;
const int MAXT = 2503;

int n, m, t;
int a[MAXN][MAXN];

int f[MAXN][MAXN][MAXT][2]; // 表示第i块木板的前j个格子粉刷k次得到的最高分数,并且当前正在粉刷0/1
int dp[MAXN][MAXT];

signed main() {
    cin >> n >> m >> t;
    for (int i = 1; i <= n; i++) {
        string s;
        cin >> s;
        for (int j = 0; j < m; j++) {
            a[i][j + 1] = s[j] - '0';
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int k = 1; k <= t; k++) {
            for (int j = 1; j <= m; j++) {
                const int c = a[i][j]; // 当前格子的颜色
                // 刷当前的颜色
                f[i][j][k][c] = max(f[i][j - 1][k][c] + 1, f[i][j - 1][k - 1][!c] + 1);
                // 不刷当前的颜色
                f[i][j][k][!c] = max(f[i][j - 1][k][!c], f[i][j - 1][k - 1][c]);
            }
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) { // 前i个木板
        for (int j = 1; j <= t; j++) { // 一共粉刷j次
            for (int k = 1; k <= j; k++) { // 在当前木板粉刷k次
                // 更新答案
                dp[i][j] = max(dp[i][j], max(f[i][m][k][0], f[i][m][k][1]) + dp[i - 1][j - k]);
                ans = max(ans, dp[i][j]);
            }
        }
    }
    cout << ans << '\n';
    return 0;
}

标签:include,洛谷,木板,格子,int,题解,粉刷,MAXN,P4158
From: https://www.cnblogs.com/wxy3265/p/18160371

相关文章

  • 列表删除按钮,分页错位问题解决思路 table delete page loadTable
    列表删除按钮,分页错位问题解决思路this.$api('/xxx/xxx/deletexxx',{ids:id}).then(res=>{if(res.status!==20)returnthis.$Message.destroy()this.$Message.success('删除成功')if(this.tableData.leng......
  • node: /lib64/libm.so.6: version `GLIBC_2.27‘ not found问题解决方案
    问题centos7服务器使用nvm或n安装的16以后的高版本node,均会出现以下问题解决1.升级gcc与make#升级GCC(默认为4升级为8)yuminstall-ycentos-release-sclyuminstall-ydevtoolset-8-gcc*ln-s/opt/rh/devtoolset-8/root/bin/gcc/usr/bin/gccln-s/opt/rh/devtool......
  • P10371 「LAOI-4」石头 题解
    原题链接:P10371。首先我们设\(l_{i,0/1}\)表示\(i\)左边的第一,二个比\(a_i\)大的数的位置。\(r_{i,0/1}\)同理。考虑一个区间\([L,R]\)在什么时候满足条件,设\(p,q\)分别为区间中最大/次大值的位置,我们分三种情况讨论。情况一:\(L<p<R\)。考虑从\(L,R\)开......
  • 洛谷题单指南-动态规划2-P1439 【模板】最长公共子序列
    原题链接:https://www.luogu.com.cn/problem/P1439题意解读:求最长公共子序列的长度。解题思路:1、O(n^2)的方法:动态规划设两个排列为a,b设dp[i][j]表示a[1~i]与b[1~j]的最长公共子序列长度根据公共子序列结尾是否包含a[i]、b[j]是否相等分情况讨论:如果a[i]==b[j]  则结尾......
  • 洛谷题解-官方题单-递归与递推
    P1255数楼梯原题链接题目描述楼梯有N阶,上楼可以一步上一阶,也可以一步上二阶。编一个程序,计算共有多少种不同的走法。对于60%的数据,N≤50;对于100%的数据,1≤N≤5000。思路:每次有2种方法上楼梯,要么上一阶,要么上二阶。第一种:得50分的做法是可以用递归来解:点击查看代码......
  • [题解][2021浙江CCPC] Fair Distribution
    题目描述给定两个数n,m,每次操作可以让n-1或者m+1,求使m%n==0的最少操作数量。题解设进行n-t次操作,使n变成t。若m%t不为0,此时的操作数量为:n-t+t-m%t。若m%t==0,操作数量为n-t。那么只需要枚举t就可以解决此题。但会发现t的范围从1-n过大,考虑将t的范围限制在1-sqrt(m),且每次分别......
  • [题解]P5656 【模板】二元一次不定方程 (exgcd)
    P5656【模板】二元一次不定方程(exgcd)若存在\(ax+by=c\),则可以根据特解\(x,y\)求出任意通解\(x',y'\):\(\begin{cases}x'=x+k*\frac{b}{\gcd(a,b)}\\y'=y-k*\frac{a}{\gcd(a,b)}\end{cases}(k\in\mathbb{Z})\)求特解的方法是「扩展欧几里得(exgcd)」,如果没接触过可以先阅读......
  • [题解][2021浙江CCPC] String Freshman
    题目描述有一份错误的字符串匹配算法,计算S串里有几个T串(只要有一个元素不同,则视为不同的串)。现在输入T串,判断能否构造S串让该算法不通过。intFind_Answer(){intj=1,ans=0;for(inti=1;i<=n;i++){if(S[i]!=T[j])j=1;if(S[......
  • 洛谷题单指南-动态规划2-P2758 编辑距离
    原题链接:https://www.luogu.com.cn/problem/P2758题意解读:对a字符串最少操作几次可以变成b字符串,看似无从下手,可以从内部递推关系着手。解题思路:设dp[i][j]表示将a字符串1~i变成b字符串1~j的最少操作次数,字符串下标从1开始。如何思考递推?可以从最后一步为切入点!最后一步对a[i]......
  • 「实用」如何在洛谷上正确的抄题解
    前言看到这个标题,估计一群人又要开始躁动不安了……等一下,如果是洛谷的管理员看到了这篇文章,不要把我给封了,我是在教各位刚入门的小萌新,也就是以后的神犇们如何切水题呢!本文没有任何反对洛谷的意思,坚决支持kkk!好了,进入今天的正题,“如何在洛谷上正确的抄题解”这个标题直接概括......