zoukankan      html  css  js  c++  java
  • [Codeforces 946D]Timetable

    Description

    题库链接

    给你一个 (N imes M)(01) 矩阵,你可以从中将一些 (1) 变为 (0) ,最多 (K) 次。使操作之后使得每行最远的 (1) 间距和最小。输出最小值。

    (1leq N,M,Kleq 500)

    Solution

    显然可以预处理一个数组 (a_{i,j}) 表示第 (i) 行操作 (j) 次后最小的间距。这个可以用 (O(N^3)) 枚举出来的。

    其次记 (f_{i,j}) 表示前 (i) 行操作 (j) 次后,最小间距和,也是 (O(N^3))(DP)

    最后答案就是 (minlimits_{i=1}^k f_{n,i})

    Code

    //It is made by Awson on 2018.3.10
    #include <bits/stdc++.h>
    #define LL long long
    #define dob complex<double>
    #define Abs(a) ((a) < 0 ? (-(a)) : (a))
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
    #define writeln(x) (write(x), putchar('
    '))
    #define lowbit(x) ((x)&(-(x)))
    using namespace std;
    const int N = 500, INF = ~0u>>1;
    void read(int &x) {
        char ch; bool flag = 0;
        for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
        for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
        x *= 1-2*flag;
    }
    void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
    void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); }
    
    int n, m, k, a[N+5][N+5], b[N+5], top, len, l[N+5];
    char ch[N+5];
    int f[N+5][N+5];
    
    void get_a(int id) {
        a[id][top] = 0;
        for (int i = 1; i <= top; i++)
        for (int j = 1; j+i-1 <= top; j++)
            a[id][top-i] = Min(a[id][top-i], b[j+i-1]-b[j]+1);
    }
    void work() {
        read(n), read(m), read(k);
        memset(a, 127/3, sizeof(a)); memset(f, 127/3, sizeof(f));
        for (int i = 1; i <= n; i++) {
        scanf("%s", ch); top = 0, len = strlen(ch);
        for (int j = 0; j < len; j++) if (ch[j] == '1') b[++top] = j;
        get_a(i); l[i] = top;
        }
        f[0][0] = 0;
        for (int i = 1; i <= n; i++)
        for (int j = 0; j <= k; j++)
            for (int q = 0; q <= j; q++)
            f[i][j] = Min(f[i][j], f[i-1][q]+a[i][j-q]);
        int ans = INF; for (int i = 0; i <= k; i++) ans = Min(ans, f[n][i]);
        printf("%d
    ", ans);
    }
    int main() {
        work(); return 0;
    }
  • 相关阅读:
    bzoj3505 数三角形 组合计数
    cogs2057 殉国 扩展欧几里得
    cogs333 荒岛野人 扩展欧几里得
    bzoj1123 BLO tarjan求点双连通分量
    poj3352 road construction tarjan求双连通分量
    cogs1804 联合权值 dp
    cogs2478 简单的最近公共祖先 树形dp
    cogs1493 递推关系 矩阵
    cogs2557 天天爱跑步 LCA
    hdu4738 Caocao's Bridge Tarjan求割边
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8540196.html
Copyright © 2011-2022 走看看