[SCOI2009]粉刷匠(分组背包)
时间:2020-05-29
本文章向大家介绍[SCOI2009]粉刷匠(分组背包),主要包括[SCOI2009]粉刷匠(分组背包)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Problem
windy有 N 条木板需要被粉刷。 每条木板被分为 M 个格子。 每个格子要被刷成红色或蓝色。
windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。 每个格子最多只能被粉刷一次。
如果windy只能粉刷 T 次,他最多能正确粉刷多少格子?
一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。
Solution
很容易发现这是一道背包问题。
我们发现一共有n条木板,每个木板之间没有关系,所以我们可以想到用分组背包。
设子状态$dp[i][j]$代表处理到第i组刷j次最多能粉刷对多少格子。
有组之间的转移方程$dp[i][j] = max(dp[i-1][j], dp[i-1][j-k]+val(i,k))$
其中$val(i,k)$代表第i个木板刷k次所能刷对的最多格子数。
现在考虑如何求出$val(i,k)$。我们发现只有一维次数是肯定不行的,得再加一维代表刷1-j的格子。
所以我们得到了组内价值的子状态:$f[i][j][k]$代表刷第i个木板的1-i,刷k次能刷对的最大格子数,显然i那一维是可以省略的。
有转移方程$f[j][k] = max(f[j][k], f[l][k-1]+max(val2(l+1, j, 1), val2(l+1, j, 0)))$,其中$val2(x, y, u)$代表从x到y全部刷u能刷对的最大格子数。
val2可以用前缀和做到。
然后这道题就迎刃而解了。
Code
/* dp[i][j] 代表前 i 个木板,粉刷 j 次可以粉刷正确的次数 dp[i][j] = max(dp[i-1][j], dp[i-1][j-k]+f[m][k]); 这里又要引入一个数组 f f[i][j] 代表位置从 1 到 i 粉刷 j 次的最大粉刷正确次数 对于每一组 f 都是不一样的,要从新求 */ #include <iostream> #include <cstdio> #include <cstring> using namespace std; int N, M, T; char s[55]; int dp[55][2510]; int f[55][55]; int sum[55]; int ans; int main() { scanf("%d%d%d", &N, &M, &T); for (int i = 1; i <= N; i++) { scanf("%s", s + 1); for (int j = 1; j <= M; j++) { sum[j] = sum[j - 1] + s[j] - '0'; } //因为每个格子只能被刷一遍,所以每次被刷的次数只会到 m for (int t = 1; t <= M; t++) { for (int j = 1; j <= M; j++) { f[j][t] = 0;//初始化为 0 for (int k = 0; k < j; k++) { //计算 f[j][t] f[j][t] = max(f[j][t], f[k][t - 1] + max((sum[j] - sum[k]), j - k - (sum[j] - sum[k]))); } } } for (int t = 1; t <= T; t++) { for (int j = 1; j <= min(M, t); j++) { dp[i][t] = max(dp[i][t], dp[i - 1][t - j] + f[M][j]); ans = max(ans, dp[i][t]); } } } cout << ans; return 0; }
原文地址:https://www.cnblogs.com/zcr-blog/p/12989068.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 浅谈Linux的编码及编码转换方法
- 在 Linux 上用 DNS 实现简单的负载均衡的方法
- centos7.2.1511安装jdk1.8.0_151及mysql5.6.38的方法
- Linux CentOS使用crontab设置定时重启的方法
- centos安装php5、卸载php、安装php7的教程
- centos7中crontab定时计划任务5分钟一次命令写法
- Ubuntu16.04 安装Teamviewer的教程详解
- 01 . OpenResty简介部署,优缺点,压测,适用场景及用Lua实现服务灰度发布
- 详解Linux iptables 命令
- 详解fedora 开启 apache 并 开启目录浏览模式
- CentOS新建用户并使能密钥登录的方法
- Linux系统扩容根目录磁盘空间的操作方法
- Linux如何查看进程栈信息示例
- linux查看硬盘大小与挂载硬盘的实现
- centos6.5 安装hadoop1.2.1的教程详解【亲测版】