1296: [SCOI2009]粉刷匠

Time Limit: 10 Sec Memory Limit: 162 MB

Submit: 2544 Solved: 1466

[Submit][Status][Discuss]

Description

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

Input

输入文件paint.in第一行包含三个整数,N M T。 接下来有N行,每行一个长度为M的字符串,’0’表示红色,’1’表示蓝色。

Output

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

Sample Input

3 6 3

111111

000000

001100

Sample Output

16

HINT

30%的数据,满足 1 <= N,M <= 10 ; 0 <= T <= 100 。 100%的数据,满足 1 <= N,M <= 50 ; 0 <= T <= 2500 。

题解

本蒟蒻不会什么太高深的做法,就猛写了一发毒瘤dp,莫名其妙过了

dp[i][j][k][0/1/2]表示第i行第j列一共粉刷了k次,0/1/2分别表示当前格子没有涂色/涂了错的颜色
/涂了对的颜色, 然后我们考虑逐格转移: 当j=1也就是出于每行的第一个位置时,我们要考虑上一行的最后一个位置, 即 dp[i][j][k][0]=max(dp[i-1][m][k][1],max(dp[i-1][m][k][2],dp[i-1][m][k][0])); dp[i][j][k][1]=max(dp[i-1][m][k-1][2],max(dp[i-1][m][k-1][1],dp[i-1][m][k-1][0])); dp[i][j][k][2]=max(dp[i-1][m][k-1][2],max(dp[i-1][m][k-1][1],dp[i-1][m][k-1][0]))+1;
其余位置要考虑这个格子颜色是否和前一个格子的颜色相等,如果相等,就有 dp[i][j][k][2]=dp[i][j-1][k][2]+1;
可以直接接上 dp[i][j][k][1]=max(dp[i][j-1][k][1],dp[i][j-1][k-1][0]);
前面涂错或不涂 dp[i][j][k][0]=max(dp[i][j-1][k][0],dp[i][j-1][k][1]);
前面涂错或不涂
如果不相等, dp[i][j][k][2]=max(dp[i][j-1][k-1][2],max(dp[i][j-1][k][1],dp[i][j-1][k-1][0]))+1;
前面可能有三种情况 dp[i][j][k][1]=max(dp[i][j-1][k][2],dp[i][j-1][k-1][0]);
涂对或不涂 dp[i][j][k][0]=max(dp[i][j-1][k][0],dp[i][j-1][k][2]);
涂对或不涂

可以用滚动数组压掉第一维,这样空间复杂度是O(nT),时间复杂度是O(nmT),还是可以过的

代码

#include<bits/stdc++.h>

using namespace std;
const int MAXN = 55; int n,m,t,dp[3][MAXN][2505][3];
bool col[MAXN][MAXN]; int main(){
scanf("%d%d%d",&n,&m,&t);
for(register int i=1;i<=n;i++){
char c[MAXN];
scanf("%s",c+1);
for(register int j=1;j<=m;j++)
col[i][j]=c[j]-'0';
}
for(register int i=1;i<=n;i++)
for(register int j=1;j<=m;j++)
for(register int k=1;k<=t;k++){
if(j==1){
dp[i&1][j][k][0]=max(dp[(i-1)&1][m][k][1],dp[(i-1)&1][m][k][0]);
dp[i&1][j][k][0]=max(dp[i&1][j][k][0],dp[(i-1)&1][m][k][2]);
dp[i&1][j][k][1]=max(dp[(i-1)&1][m][k-1][1],dp[(i-1)&1][m][k-1][0]);
dp[i&1][j][k][1]=max(dp[i&1][j][k][1],dp[(i-1)&1][m][k-1][2]);
dp[i&1][j][k][2]=max(dp[(i-1)&1][m][k-1][1],dp[(i-1)&1][m][k-1][0])+1;
dp[i&1][j][k][2]=max(dp[i&1][j][k][2],dp[(i-1)&1][m][k-1][2]+1);
}
else{
if(col[i][j]==col[i][j-1]){
dp[i&1][j][k][2]=dp[i&1][j-1][k][2]+1;
dp[i&1][j][k][1]=max(dp[i&1][j-1][k][1],dp[i&1][j-1][k-1][0]);
dp[i&1][j][k][0]=max(dp[i&1][j-1][k][0],dp[i&1][j-1][k][1]);
}
else{
dp[i&1][j][k][2]=max(dp[i&1][j-1][k][1],dp[i&1][j-1][k-1][0])+1;
dp[i&1][j][k][2]=max(dp[i&1][j-1][k-1][2]+1,dp[i&1][j][k][2]);
dp[i&1][j][k][1]=max(dp[i&1][j-1][k][2],dp[i&1][j-1][k-1][0]);
dp[i&1][j][k][0]=max(dp[i&1][j-1][k][0],dp[i&1][j-1][k][2]);
}
}
// cout<<dp[i][j][k][0]<<" "<<dp[i][j][k][1]<<" ";
// cout<<dp[i][j][k][2]<<endl;
}
printf("%d",max(max(dp[n&1][m][t][0],dp[n&1][m][t][1]),dp[n&1][m][t][2]));
return 0;
}

BZOJ 1296(SCOI 2009) 粉刷匠的更多相关文章

  1. 【BZOJ 1296】 [SCOI2009]粉刷匠

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] f[i][j][k]表示第i行前j列刷了k次,最大满意度 f[][j][k]=max{f[i][l][k],f[i][l][k-1] ...

  2. [BZOJ 1026] [SCOI 2009] Windy数 【数位DP】

    题目链接:BZOJ - 1026 题目分析 这道题是一道数位DP的基础题,对于完全不会数位DP的我来说也是难题.. 对于询问 [a,b] 的区间的答案,我们对询问进行差分,求 [0,b] - [0,a ...

  3. [BZOJ 1297][SCOI 2009]迷路(矩阵快速幂)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1297 分析:如果每条边的边权都是1,那么就相当于对邻接矩阵自乘T次(因为写一下递推式子 ...

  4. BZOJ 1024 SCOI 2009 生日快乐 深搜

    题目大意:有一块蛋糕,长为X,宽为Y.如今有n个人来分这块蛋糕,还要保证每一个人分的蛋糕的面积相等.求一种分法,使得全部的蛋糕的长边与短边的比值的最大值最小. 思路:刚拿到这个题并没有什么思路.可是定 ...

  5. bzoj 1024 [ SCOI 2009 ] 生日快乐 —— 递归

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1024 因为每次把一块切成两块,所以可以枚举从哪里切开,然后递归求解: 一开始用了不太对的贪心 ...

  6. BZOJ 1296: [SCOI2009]粉刷匠 分组DP

    1296: [SCOI2009]粉刷匠 Description windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上 ...

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

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

  8. 2014.7.8模拟赛【笨笨当粉刷匠】|bzoj1296 [SCOI]粉刷匠

    笨笨太好玩了,农田荒芜了,彩奖用光了,笨笨只好到处找工作,笨笨找到了一份粉刷匠的工作.笨笨有n条木板需要被粉刷.每条木板被分成m个格子,每个格子要被刷成红色或蓝色.笨笨每次粉刷,只能选择一条木板上一段 ...

  9. 1296: [SCOI2009]粉刷匠[多重dp]

    1296: [SCOI2009]粉刷匠 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1919  Solved: 1099[Submit][Statu ...

随机推荐

  1. 借用数组对象的prototype给数组扩充降维方法

    原理:只要是一个对象,他都有一个prototype原型对象,保存共有的属性和方法. <!DOCTYPE html> <html lang="en"> < ...

  2. Linux网络编程 了解

    IPV4 -- IP地址分类:主机号是区分主机的,网络号是区分网段的 子网掩码是对主机号进行划分子网用的 举例说明: 对 192.168.1.0网段划分4个 其子网掩码 : 拿出主机号的两个位进行划分 ...

  3. ubuntu下网页视频或音频无法播放

    有时,网页的音频或视频内容在 Firefox 下无法正常下载和播放.所需的插件没找到.过期.被阻止.和其他插件或扩展冲突,或者是内容由于某种原因被阻止.本文会帮助你解决这些问题. Flash 插件 F ...

  4. vue中数据绑定遇到的问题

    <!-- 使用element中的表格组件,在编辑的时候传递每行的数据 --> <el-button size="small" type="success ...

  5. Linkedlist 详解

    基本介绍 Linkedlist基于链表的动态数组(双向链表): 可以被当作堆栈(后进先出).队列(先进先出)或双端队列进行操作. 数据添加删除效率高,只需要改变指针指向即可,但是访问数据的平均效率低, ...

  6. bzoj_auto_submiter(辣鸡Py毁我青春系列)

    听说你们的bzoj小号都很厉害? 不如试试bzoj金坷垃——bzoj_auto_submiter! 把所有的代码拖进解压后的文件夹,然后双击run.cmd. 看到有chrome浏览器窗口弹出来不要慌, ...

  7. NX二次开发-UFUN和NXOpen结合开发中Tag_t对象与TaggedObject对象转换方法

    本文通过举四个例子来告诉大家在NX二次开发过程中会经常用到UFUN和NXOpen结合去开发,在UFUN中我们得到的是Tag_t对象,在NXOpen中得到的是TaggedObject对象,这两个是需要进 ...

  8. Apache负载均衡

    Apache负载均衡 Apache也是可以实现负载均衡的.Apache的负载均衡主要是通过mod_proxy_balancer实现的.那么,apache负载均衡的配置方法是什么样的? 在apache的 ...

  9. JavaScript笔记 - Object对象特性的应用

    可以依据js对象中key是永远不会重复的原则,来模拟Map类型以及去除数组重复项. 1.模拟Map类型 (1)构造Map对象 function Map(){ //private var obj = { ...

  10. maven+scala+idea 环境构建

    组建信息 组件 版本 下载地址 maven 3.6.1 https://maven.apache.org/ jdk jdk1.8.0 https://www.oracle.com/technetwor ...