Codeforces #576 Rectangle Painting 1 | div1D | div2F | DP | Rustlang
大意
n*n
正方形 有黑有白
每次可以选择一个 矩形把它全变成白色,代价是max(长,宽)
求吧 整个正方形 全变白 的最小代价
数据范围
n <= 50
题解
首先如果 我们刷了两个有相邻边或重叠的 白色矩形
那么 假设他们的代价分别为 x和y
那么 一定有 一个 边长为x+y的正方形 完全覆盖了这两个白色矩形
dis|row| <= rowX+roxY <= costX+costY = x+y
dis|col| <= colX+roxY <= costX+costY = x+y
所以综上所述 两两不重叠
再来,证明 如果 最优结果要么选择的单一矩形,要么一定能 垂直 或水平分化,即是 不会出现类似 弦图 这样的分化
假设存在,那么意味这有n*m
的矩形,和对应选择多个图画方案,使得
- 图画方案是最优的
- 子选择矩形个数大于1
- 不存在按竖着 分化,或横着分化,使得子选择被分开
对于横向来看,意味着任意选择分割线 都会和最优解的选择中的矩形的横着的边冲突,
也就意味着,从min横向点 到 max横向点,所有点都有边。
即是,从横向看 最优解的 cost 横向 >= (max横向点-min横向点)
由对称性,从纵向看 最优解的 cost 纵向 >= (max纵向-min纵向点)
那么我们直接用 相应的大矩形(max横向点-min横向点,max纵向-min纵向点) 从面积上覆盖 最优解答
即
大矩形 cost (从覆盖关系,和最优解答定义)>= 最优解答cost (根据横向和纵向边的关系)>= 大矩形cost
综上
- 没有重叠 至多相邻
- 要么 单一选择的矩形(如大矩形),要么可纵向 或 可横向分割
所以
dp[top i0 -> bottom i1][left j0 -> right j1]
=min(
max(i1-i0,j1-j0),
dp[i0 -> k][j0->j1] + dp[k+1->i1][j0->j1],
dp[i0 -> i1][j0 -> k] + dp[i0->i1][k+1->j1],
)
时间复杂度 O(枚举长 * 枚举宽 * 枚举左上角坐标 * 状态转移) = O(n * n * (n * n) * n) = O(n^5)
能过
代码 Rust
920ms/1s 强行 过了,慢应该是用Vec的原因,如果换成c++的直接数组的话,应该能快很多,// 我暂时还没玩会Rust的多维数组
#![allow(unused_imports)]
use std::cmp::*;
use std::collections::*;
struct Scanner {
buffer : std::collections::VecDeque<String>
}
impl Scanner {
fn new() -> Scanner {
Scanner {
buffer: std::collections::VecDeque::new()
}
}
fn next<T : std::str::FromStr >(&mut self) -> T {
if self.buffer.len() == 0 {
let mut input = String::new();
std::io::stdin().read_line(&mut input).ok();
for word in input.split_whitespace() {
self.buffer.push_back(word.to_string())
}
}
let front = self.buffer.pop_front().unwrap();
front.parse::<T>().ok().unwrap()
}
}
fn main() {
let mut s = Scanner::new();
let n : usize = s.next();
// dp[top i][left j][bottom i][right j] 全部清理 需要的最小代价
let mut dp = vec![vec![vec![vec![0;n+1];n+1];n+1];n+1];
for i in 0..n {
let line:String = s.next();
for (j, ch) in line.chars().enumerate() {
if ch == '#' {
dp[i][j][i][j] = 1;
}
}
}
// 枚举 矩形大小从小到大
for i in 0..n {
for j in 0..n {
if i == 0 && j == 0 {
continue;
}
// 枚举 矩形左上角坐标
for p in 0..n-i {
for q in 0..n-j {
// 右下角坐标
let (x,y) = (i+p,j+q);
dp[p][q][x][y] = max(i,j)+1;
for k in p..x {
dp[p][q][x][y]=min(dp[p][q][x][y],dp[p][q][k][y]+dp[k+1][q][x][y]);
}
for k in q..y {
dp[p][q][x][y]=min(dp[p][q][x][y],dp[p][q][x][k]+dp[p][k+1][x][y]);
}
}
}
}
}
println!("{}",dp[0][0][n-1][n-1]);
}
Codeforces #576 Rectangle Painting 1 | div1D | div2F | DP | Rustlang的更多相关文章
- Codeforces - 1198D - Rectangle Painting 1 - dp
https://codeforces.com/contest/1198/problem/D 原来是dp的思路,而且是每次切成两半向下递归.好像在哪里见过类似的,貌似是紫书的样子. 再想想好像就很显然的 ...
- Codeforces 1198E Rectangle Painting 2 最小点覆盖(网络流)
题意:有一个n * n的棋盘,每个棋盘有某些矩形区域被染成了黑色(这些矩形区域有可能相交),问把所有黑色区域染成白色的最小花费是多少?你每次可以选择把一个矩形区域染成白色,花费是染色的矩形区域长和宽的 ...
- codeforces 1198E Rectangle Painting 2 最小点覆盖
题目传送门 题意: 有一个$n∗n$的网格,网格中有一些矩形是黑的,其他点都是白的. 你每次可以花费$ min (h,w)$的代价把一个$h*w$的矩形区域变白.求把所有黑格变白的最小代价. 思路: ...
- Codeforces 219D. Choosing Capital for Treeland (树dp)
题目链接:http://codeforces.com/contest/219/problem/D 树dp //#pragma comment(linker, "/STACK:10240000 ...
- [CodeForces - 1272D] Remove One Element 【线性dp】
[CodeForces - 1272D] Remove One Element [线性dp] 标签:题解 codeforces题解 dp 线性dp 题目描述 Time limit 2000 ms Me ...
- Painting The Wall 期望DP Codeforces 398_B
B. Painting The Wall time limit per test 1 second memory limit per test 256 megabytes input standard ...
- Codeforces Round #256 (Div. 2) C. Painting Fence 或搜索DP
C. Painting Fence time limit per test 1 second memory limit per test 512 megabytes input standard in ...
- Codeforces Round #233 (Div. 2)D. Painting The Wall 概率DP
D. Painting The Wall ...
- CodeForces 1198D 1199F Rectangle Painting 1
Time limit 1000 ms Memory limit 262144 kB 解题思路 一堆循环嵌套的那种dp,不好想.但是可以搜啊,很暴力的.记忆化一下就好. 我们定义搜索函数\(\text{ ...
随机推荐
- sqlserver关于时间的一些语句
/* 去掉时间的时分秒 */ CONVERT(CHAR(10),operate_time,120) /* 所有的天数增加一天 */ DATEADD(day,1,t.operate_time) /* 返 ...
- luoguP2590 [ZJOI2008]树的统计(树链剖分)
luogu P2590 [ZJOI2008]树的统计 题目 #include<iostream> #include<cstdlib> #include<cstdio> ...
- 学习servlet时出现的一些问题
此篇用来记录学习servlet时遇到的一些问题,谨防以后再犯. 问题1.导入的web项目,servlet中导入的包名报错. (1)缺少相关包,推荐一个网站下载jar包很方便http://mvnrepo ...
- hdu6333 Problem B. Harvest of Apples(组合数+莫队)
hdu6333 Problem B. Harvest of Apples 题目传送门 题意: 求(0,n)~(m,n)组合数之和 题解: C(n,m)=C(n-1,m-1)+C(n-1,m) 设 ...
- python学习二十四天函数参数之默认参数
函数参数就是向函数传递参数,可以传递一个,可以是更多个,有的参数有值,有的没有,函数可以设置默认参数,默认参数必须放参数最后面. 1,不传递参数,设置默认参数 def hello(a,b,c='123 ...
- Centos6.5 使用YUM安装MariaDB
1,第一步 [xxxxxx]$ cd /etc/yum.repos.d [xxxxxx]$ vi MariaDB.repo # MariaDB 10.0 CentOS repository list ...
- 图解git中的最常用命令
图解git中的最常用命令 Git命令参考手册(文本版) git init # 初始化本地git仓库(创 ...
- 【问题解决方案】GitHub仓库重构之将某个或某些文件夹移动到其他文件夹内
仓库重构时遇到的问题,在GitHub页面里好像没有类似的操作按钮? 搜了一下好像要用到一些命令比如rm等,但是我对Linux类的命令不是很熟悉 于是想试试曲线救国,先把远程库的文件pull到本地,在本 ...
- JavaScript原型&原型链
原型&原型对象 先来一段简单的代码: function Fun(name) { this.name = name } var obj = new Fun('obj') JavaScript中的 ...
- Djano中static和media文件路径的设置
对于常用的css.js.image和常用的工具类在django项目中要设置一个全局的路径,对所有的app都可以访问到这个路径下的文件 1在django项目的setting文件中设置对应的static和 ...