【每日一题】粉刷匠 题解

[SCOI2009]粉刷匠

https://ac.nowcoder.com/acm/problem/20273

Solution

一看数据范围, 肯定是个
但是这个数据范围做不了状压
考虑普通的
这个问题的难点在于他是二维的情况(多个木块)
那么如果是一维的情况怎么做呢?我们先考虑一下
表示第 个木板粉刷 次涂了前面 个格子的正确格子数
因为只有两种颜色, 对于某一块木板, 我们可以维护一个前缀和 表示第 个木板的第 个格子前蓝色格子的数目
对于单个木板有
表示对第 块木板涂了 次, 此时到第 个位置可以从第 块木板的涂了 次的第 个位置转移过来
对于要么取蓝色, 要么取红色, 我们取个 即可, 的蓝色格子 的红色格子
此时再考虑多个木板情况
显然有
表示到第 个木板涂了 次可以从 第个木板涂了 次转移过来

Code

/*
  autor: Kurisu
  2020年4月30日16:48:49
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const long long inf = 1e18;
const int N = 1e6 + 5;
const double eps = 1e-10;
const ll mod = 23333333333333333;
ll dp[55][2505]; // 前 i 个木板粉刷 j 次的正确格子数
ll f[55][2505][55]; // 第 i 个木板粉刷 j 次涂了前面 k 个格子的正确格子数
ll sum[55][55]; // 第 i 个木板的第 j 个格子前蓝色格子的数目
int main() {
  int n, m, t;
  cin >> n >> m >> t;
  string s;
  for(int i = 1; i <= n; i++) {
    cin >> s;
    s = ' ' + s;
    sum[i][0] = 0;
    for(int j = 1; j <= m; j++) {
      sum[i][j] = sum[i][j - 1] + (s[j] == '1');
    }
  }
  for(int i = 1; i <= n; i++) {
    for(int j = 1; j <= m; j++) {
      for(int k = 1; k <= m; k++) {
        for(int l = j - 1; l < k; l++) {
          f[i][j][k] = max(f[i][j][k], f[i][j - 1][l] + max(sum[i][k] - sum[i][l], k - l - sum[i][k] + sum[i][l]));
        }
      }
    }
  }
  ll ans = 0;
  for(int i = 1; i <= n; i++) {
    for(int j = 1; j <= t; j++) {
      for(int k = 0; k <= min(j, m); k++) {
        dp[i][j] = max(dp[i][j], dp[i - 1][j - k] + f[i][k][m]);
        ans = max(ans, dp[i][j]);
      }
    }
  }
  cout << ans << "\n";
  return 0;
}
Kurisu与牛客的每日一题 文章被收录于专栏

每日一题

全部评论

相关推荐

不愿透露姓名的神秘牛友
06-29 17:30
找实习找着找着就要进入7月了,马上秋招也要开始了,找实习还有意义吗?
绝迹的星:有面就面, 没面上就当日薪4位数大佬免费培训, 面上了再考虑要不要实习
点赞 评论 收藏
分享
认真搞学习:这么良心的老板真少见
点赞 评论 收藏
分享
深夜书店vv:腾讯是这样的,去年很多走廊都加桌子当工区
点赞 评论 收藏
分享
我:“加班需要有加班工资。”&nbsp;hr:“为什么?”&nbsp;哈哈哈哈哈哈哈离大谱
juntenor:你确实太理想化了,对社会不了解呀。这个和HR没有关系,这是国内特色,不然怎么还会有外包就这种逆天的存在呢。
点赞 评论 收藏
分享
评论
8
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务