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. .Net平台调用の初识

    前言 工作过程中难免遇到混合编程,现在我们要谈的是C#和c++语言的编程.C#要调用C++的库目前可选主要有两种方式:Com技术和平台调用(P/Invoke).现在我们要谈的是P/Invoke技术. ...

  2. tzfile - 时区信息

    SYNOPSIS #include <tzfile.h> DESCRIPTION 时区信息文件被 tzset(3) 使用, 其开头为特征字符"TZif", 以此标示该文 ...

  3. Codeigniter Session: Configured save path is not a directory

    Codeigniter 3.x Message: Session: Configured save path '' is not a directory, doesn't exist or canno ...

  4. CentOS7-安装最新版本GIT(git version 2.18.0)

    Git安装方式有两种一种是yum安装一种是编译安装: 一.yum命令安装,此方法简单,会自动安装依赖的包,而且会从源里安装最新的版本,如果仓库不是最新的话安装的也不是最新Git. sudo yum i ...

  5. leetcood学习笔记-83-删除链表中的重复元素

    题目描述: 第一次提交: class Solution: def deleteDuplicates(self, head: ListNode) -> ListNode: if head==Non ...

  6. c++中创建二维数组的几种方法

    一.用new申请内存空间 int **dp=new int*[n];//动态申请二维数组nxm ;i<n;++i){ dp[i]=new int[m]; } 二.用malloc申请内存空间 ; ...

  7. Java语法清单-快速回顾(开发)

    Java CheatSheet 01.基础 hello,world! public static void main(String[] args) { System.out.println(" ...

  8. NX二次开发-创建CSYS坐标系UF_CSYS_create_csys

    NX9+VS2012 #include <uf.h> #include <uf_csys.h> #include <uf_mtx.h> UF_initialize( ...

  9. favicon.ico请求处理

    favicon.ico 图标用于收藏夹图标和浏览器标签上的显示,如果不设置,浏览器会请求网站根目录的这个图标,如果网站根目录也没有这图标会产生 404. 出于优化的考虑,要么就有这个图标,要么就禁止产 ...

  10. 构建高性能高并发Java系统 .

    转:http://blog.csdn.net/nengyu/article/details/7591854 场景这里指的高性能高并发服务器是一个有状态的服务,可以理解成web或者socket服务器,每 ...