[洛谷P4158][SCOI2009]粉刷匠(动态规划)

  • 题目描述
  • 输入描述
  • 输出描述
  • 示例
    • 输入
    • 输出
  • 题目思路
  • 代码
  • 欢迎关注微信公众号:Java后台开发

题目描述

windy有 N 条木板需要被粉刷。 每条木板被分为 M 个格子。 每个格子要被刷成红色或蓝色。
windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。
如果windy只能粉刷 T 次,他最多能正确粉刷多少格子?
一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。

输入描述

第一行包含三个整数,N M T。
接下来有N行,每行一个长度为M的字符串,'0’表示红色,'1’表示蓝色。
30%的数据,满足 1 <= N,M <= 10 ; 0 <= T <= 100 。
100%的数据,满足 1 <= N,M <= 50 ; 0 <= T <= 2500 。

输出描述

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

示例

输入

3 6 3
111111
000000
001100

输出

16

题目思路

首先一块木板要刷的话一定会全部刷完,因为不刷或者刷错了都不算数,所以干脆刷完,即使刷错了也不要紧,有可能还能多刷对几块。例如001100,刷一次,全刷红色,就能有4块对的。

再分析一块木板刷k次最多能正确粉刷多少格子呢?
我们可以先把这块木板连续续相同颜色格子合并起来,例如001100这块板子看作2 2 2,代表有三块连续的相同颜色块数,且相邻两块颜色不同。很容易想到这块木板的粉刷一定是刷红刷蓝交替进行的,且后一次粉刷可以利用前一次粉刷的结果,所以可以用dp解决一块木板最多能正确粉刷的格子数。

用f[i][j][l]表示这块木板从左到右刷了i次,刷完了第j块,且最后一次粉刷的颜色是l,那么很容易想到转移方程:
f[i][j][l] = max(f[i][j][l],f[i-1][k][l^1]+第k+1块到第j块颜色为l的格子数)(0<=k<j)
注意第k+1块到第j块颜色为l的格子数可以提前预处理用一个数组记录下来
然后把这块木板刷k次最多能正确粉刷的格子数用一个vector保存下来

知道了一块木板刷k次最多能正确粉刷多少格子后就很容易能想到i块木板刷j次的最多正确粉刷格子数的dp解法
dp[i][j]表示前i块木板刷了j次的最多正确粉刷格子数,那么可以很容易得到状态转移方程:
dp[i][j] = max(dp[i-1][j-k]+第i块木板刷k次最多能正确粉刷的格子数)(0<=k<=木板的连续块数)
最后统计一下答案就出来了

代码

#include<bits/stdc++.h>
using namespace std;
int n,m,t,dp[55][2505],ans;
string s[55];
vector<int>v[55];//保存每一块木板粉刷k次能正确多少
void preProcess(int x)//预处理每一块木板粉刷k次能正确多少
{vector<int>y,z;int now = s[x][0]-'0',sum = 0,f[55][55][2] = {0},p[55][55][2] = {0},maxn = 0;y.push_back(0);//因为vector下标从0开始,所以加一个0代表刷0次正确0块,z.push_back(0);//z代表每一块的颜色是什么,方便后面统计第i到j块颜色为l的格子数//将木板连续相同颜色格子合并 for(int i = 0;i<m;i++){if(now==0&&s[x][i]=='0'||now==1&&s[x][i]=='1')sum++;if(now==0&&s[x][i]=='1'&&sum!=0)y.push_back(sum),z.push_back(0),now = 1,sum = 1;if(now==1&&s[x][i]=='0'&&sum!=0)y.push_back(sum),z.push_back(1),now = 0,sum = 1;}if(sum!=0)y.push_back(sum),z.push_back(s[x][m-1]-'0');sum = y.size();//预处理第i到j块颜色为l的格子数 for(int i = 0;i<sum;i++)for(int j = i;j<sum;j++)for(int k = i;k<=j;k++)for(int l = 0;l<=1;l++)p[i][j][l]+=y[k]*(z[k]==l);//得到这块木板从左到右刷i次刷完第j块且最后一次粉刷颜色为l最多能有多少格子正确 for(int i = 1;i<sum;i++)for(int j = 1;j<sum;j++)for(int k = 0;k<j;k++)for(int l = 0;l<=1;l++)f[i][j][l] = max(f[i][j][l],f[i-1][k][l^1]+p[k+1][j][l]);//统计保存这块木板结果到vector中 for(int i = 0;i<sum;i++,v[x].push_back(maxn),maxn = 0)for(int j = 0;j<sum;j++)maxn = max(maxn,max(f[i][j][0],f[i][j][1]));
}
int main()
{cin>>n>>m>>t;for(int i = 1;i<=n;i++)cin>>s[i],preProcess(i);//得到刷完第i块木板共刷了j次且最多能有多少格子正确 for(int i = 1;i<=n;i++)for(int j = 1;j<=t;j++)for(int k = 0;k<v[i].size()&&k<=j;k++)dp[i][j] = max(dp[i][j],dp[i-1][j-k]+v[i][k]);for(int i = 1;i<=n;i++)ans = max(ans,dp[i][t]);cout<<ans; return 0;
}

欢迎关注微信公众号:Java后台开发

致力于分享原创计算机与软件开发知识及SSM、Spring cloud、Redis、微服务等Java后端开发技术
公众号里还有很多开发工具及学习资料

[洛谷P4158][SCOI2009]粉刷匠(动态规划)相关推荐

  1. 【题解】洛谷P4158 [SCOI2009] 粉刷匠(DP)

    次元传送门:洛谷P4158 思路 f[i][j][k][0/1]表示在坐标为(i,j)的格子 已经涂了k次 (0是此格子涂错 1是此格子涂对)涂对的格子数 显然的是 每次换行都要增加一次次数 那么当j ...

  2. [洛谷]P4158 [SCOI2009]粉刷匠 (#线性dp+背包dp)

    题目描述 windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色. 每个格子最多只能被 ...

  3. bzoj 1296 洛谷4158 [SCOI2009]粉刷匠 题解

    题意简述 一个 n × m n\times m n×m的矩阵,每个位置珂能是粉色(0表示)或者是蓝色(1表示),然后你珂以对同一行里连续一段长度的区间染上一种颜色(覆盖型),你能染 t t t次,每次 ...

  4. 【题解】P4158 [SCOI2009]粉刷匠(DP,背包)

    [题解]P4158 [SCOI2009]粉刷匠 是一道资源规划 DP 的好题,但是我想了很久还去看了题解./kk我真菜. 题目链接 P4158 [SCOI2009]粉刷匠 - 洛谷 题意概述 发现自己 ...

  5. P4158 [SCOI2009]粉刷匠(dp)

    P4158 [SCOI2009]粉刷匠(dp) 考虑每行独立计算. 所以可以开一个三维数组:g[i][j][k]g[i][j][k]g[i][j][k]第iii行前jjj列涂了kkk次的最大值. 然后 ...

  6. P4158[SCOI2009]粉刷匠

    题目描述 windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色. 每个格子最多只能被 ...

  7. BZOJ1296:[SCOI2009]粉刷匠

    1296: [SCOI2009]粉刷匠 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2038  Solved: 1182 [Submit][Sta ...

  8. 洛谷P1133 教主的花园 动态规划

    洛谷P1133 教主的花园 动态规划 这里是环状的,但是我们并不用将他破环成链 只要枚举第一个点 根据第一个点选择最后一个选择什么就行了 然后我们进行DP 注意如果当前是 2 的话要分情况 上一次是上 ...

  9. BZOJ 1296: [SCOI2009]粉刷匠( dp )

    dp[ i ][ j ] = max( dp[ i - 1 ][ k ] + w[ i ][ j - k ] )  ( 0 <= k <= j ) 表示前 i 行用了 j 次粉刷的机会能正 ...

最新文章

  1. bootcmd 和 bootargs 环境变量
  2. nodejs 的序列化与反序列化
  3. java reactor框架_Java反应式框架Reactor中的Mono和Flux
  4. 【STM32】DMA相关函数和类型
  5. 关于Fiori应用sandbox JavaScript的两个疑问
  6. Python+Opencv实现模板匹配
  7. 从外网Thinkphp3日志泄露到杀入内网域控 - 红队攻击之域内靶机渗透实战演练
  8. linux判断usb进程命令,一种在Linux系统下审计USB设备历史使用情况的方法与流程...
  9. 华为Mate 20 X(5G)评测:6199元的5G双模旗舰手机
  10. silverlight将字符串转化为控件
  11. cmmi证书查询(cmmi认证查询网站)
  12. BSOD 0x00000133
  13. 在我的ibmR40上装osx86
  14. python爬取qq音乐歌词风变编程_爬取QQ音乐歌词
  15. mysql使用命令行导入sql脚本 报错无法插入中文
  16. gradient设置上下渐变_CSS3中渐变gradient详解
  17. [Eigen]Eigen的单位矩阵C++
  18. 有限新息率FRI信号模型
  19. python求主析取范式_求公式q→(r∧p)的析取范式。
  20. 使用ctex宏包出现的kpathsea错误

热门文章

  1. 阿里云服务器企业型如何选择配置最佳?
  2. change lan.php lanid,天融信负载均衡本地文件包含漏洞
  3. 【蒟蒻の笔记】OI中组合数学
  4. 通信:从功耗角度出发,5G相比4G,基站和终端功耗是降低了还是升高了?
  5. 中科红旗:开源的野心
  6. 论坛APP开发需要具备哪些功能
  7. 红旗linux 桌面10 下载,想要红旗桌面操作系统10(RedFlag Desktop Linux10)的请联系红旗官方...
  8. 大数据技术人年度盛事! BDTC 2016将于12月8-10日在京举行
  9. 杭州海赢科技分享2021速卖通牙科用品招商入驻规则
  10. 基于微信小程序的校园二手物品交易平台的设计与实现