Bzoj 3661: Hungry Rabbit

傳送門: http://www.lydsy.com/JudgeOnline/problem.php?id=3661
題解:
解法一:網絡流
  按天建分層圖,兩天之間一隻兔子如果都可以出行,就直接連向下一天,所有上一天能出行的兔子連到一個轉換點,轉換點再連向下一天能出行的兔子,轉換點要拆點,限制流量爲 l ,一個兔子不可以即走轉換點又直接走向下一天,所以兔子也拆點限制一下流量爲 1 即可。總流量 k 只要將源點拆點限制流量爲 k 即可。複雜度 O( 能過) 54881ms
解法二:貪心
  對於每一天貪心地找後一段能持續走最長天數的兔子,兩天之間將前一天出來的和沒出來的兔子分別排序,用前一天沒出來的將來能走天數前 l 長的兔子更新前一天出來的將來能走天數前 l 短的兔子。(正確性我也不會證QAQ)複雜度 O(mnlogn) 592ms

網絡流:

#include<bits/stdc++.h>
const int N = 805;
const int M = 805;
const int Node = N * M * 3;
const int Edge = Node * 3 * 2;
const int INF = 1e9;
struct edge {
    int y, v, next;
}mp[Edge];
int n, m, k, l, S, T, first[Node], cur[Node], s, h[Node], q[Node], match;
char ch[N][M];
void ins(int x, int y, int v) {
    //printf("x=%d y=%d v=%d\n", x, y, v);
    mp[++s] = (edge){y, v, first[x]}; first[x] = s;
    mp[++s] = (edge){x, 0, first[y]}; first[y] = s;
};
void build() {
    int t = n * m * 2; s = 1;
    for (int j = 0; j < m - 1; j++) {
        for (int i = 0; i < n; i++)
            if (ch[i][j] == '1') {
                ins((j * n + i) * 2, (j * n + i) * 2 + 1, 1);
                ins((j * n + i) * 2 + 1, t + j * 2, 1);
                if (ch[i][j + 1] == '1')
                    ins((j * n + i) * 2 + 1, ((j + 1) * n + i) * 2, 1);
            }
        for (int i = 0; i < n; i++)
            if (ch[i][j + 1] == '1')
                ins(t + j * 2 + 1, ((j + 1) * n + i) * 2, 1);
        ins(t + j * 2, t + j * 2 + 1, l);
    }
    for (int i = 0; i < n; i++)
        if (ch[i][m - 1] == '1')
            ins(((m - 1) * n + i) * 2, ((m - 1) * n + i) * 2 + 1, 1);
    t += m * 2;
    S = t + 1, T = t + 2;
    ins(S, t, k);
    for (int i = 0; i < n; i++)
        if (ch[i][0]) ins(t, i * 2, 1);
    for (int i = 0; i < n; i++)
        if (ch[i][m - 1]) ins(((m - 1) * n + i) * 2 + 1, T, 1);
}
bool bfs() {
    memset(h, 0, sizeof(h));
    for (int i = 0; i <= T; i++)
        cur[i] = first[i];
    int head = 1, tail = 1;
    h[q[head] = S] = 1;
    for (int x = q[head]; head <= tail; x = q[++head])
        for (int t = first[x]; t; t = mp[t].next)
            if (mp[t].v && !h[mp[t].y]) {
                h[mp[t].y] = h[x] + 1,
                q[++tail] = mp[t].y;
                if (mp[t].y == T) return 1;
            }
    return 0;
}
int dfs(int x, int f) {
    if (x == T) return f;
    int used = 0, b;
    for (int t = cur[x]; t; t = cur[x] = mp[t].next)
        if (h[x] + 1 == h[mp[t].y]) {
            b = dfs(mp[t].y, std::min(f - used, mp[t].v));
            mp[t].v -= b;
            mp[t ^ 1].v += b;
            used += b;
            if (used == f) return used;
        }
    h[x] = -1;
    return used;
}
int main() {
    scanf("%d%d%d%d", &n, &m, &k, &l);
    for (int i = 0; i < n; i++) scanf("%s", ch[i]);
    build();
    while (bfs()) match += dfs(S, INF);
    if (match < k) {printf("-1\n"); return 0;}
    for (int j = 0; j < m; j++) {
        for (int i = 0; i < n; i++)
            for (int t = first[(j * n + i) * 2]; t; t = mp[t].next)
                if (mp[t].y == (j * n + i) * 2 + 1 && !mp[t].v)
                    printf("%d ", i + 1);
        printf("\n");
    }
    return 0;
}

貪心:

#include<bits/stdc++.h>
const int N = 805;
struct rec {
    int num, d;
    rec() {}
    rec(int _num, int _d):
        num(_num), d(_d) {}
} a[N], b[N];
bool cmp1(const rec &a, const rec &b) {return a.d > b.d;}
bool cmp2(const rec &a, const rec &b) {return a.d < b.d;}
int n, m, k, l, d[N][N], p[N][N], cnt1, cnt2;
bool picked[N];
char ch[N];
int main() {
    scanf("%d%d%d%d", &n, &m, &k, &l);
    for (int i = 1; i <= n; i++) {
        scanf("%s", ch + 1);
        for (int j = m; j > 0; j--)
            if (ch[j] == '0')
                d[i][j] = 0;
            else
                d[i][j] = d[i][j + 1] + 1;
    }
    for (int i = 1; i <= n; i++)
        if (d[i][1]) a[++cnt1] = rec(i, d[i][1]);
    std::sort(a + 1, a + cnt1 + 1, cmp1);
    if (cnt1 < k) {printf("-1\n"); return 0;}
    for (int i = 1; i <= k; i++)
        p[1][i] = a[i].num,
        picked[a[i].num] = 1;
    for (int i = 2; i <= m; i++) {
        cnt1 = cnt2 = 0;
        for (int j = 1; j <= k; j++)
            b[++cnt2] = rec(p[i - 1][j], d[p[i - 1][j]][i]);
        for (int j = 1; j <= n; j++)
            if (!picked[j]) a[++cnt1] = rec(j, d[j][i]);
        std::sort(a + 1, a + cnt1 + 1, cmp1);
        std::sort(b + 1, b + cnt2 + 1, cmp2);
        for (int j = 1; j <= k; j++) {
            if (j <= l && a[j].d > b[j].d)
                picked[a[j].num] = 1,
                picked[b[j].num] = 0,
                std::swap(a[j], b[j]);
            p[i][j] = b[j].num;
            if (!b[j].d) {printf("-1\n"); return 0;}
        }
    }
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= k; j++)
            printf("%d ", p[i][j]);
        printf("\n");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章