bzoj4657 tower [network flow]

Posted by blogfisher on Wed, 01 Apr 2020 19:18:05 +0200

Description:
There is a map of n × mn × m. every position on the map can be air ground, turret or enemy. You need to manipulate the turret to eliminate the enemy. For each turret, there is a direction it can aim at. You need to determine its attack position in its aim direction, and if it can not attack, once a position is attacked, Then all enemies in this position will be eliminated. Ensure that for any turret, there is no other turret in all possible attack positions. Define the trajectory of the projectile as the area covered by the starting point and the ending point of the projectile. You need to find a solution so that no two trajectory of the projectile intersect

Solution:
Make complaints:
It seems to be a network flow, but I didn't figure out how to use the maximum value in the exam, so I gave up the way of cake cutting and wrote a cost flow. I found that the missile can turn, so my heart broke, and the second question didn't come out.

First of all, it can be converted to the problem that can be solved by the minimum cut. Then, for each row and column, we can find the maximum value, and the capacity between adjacent points is the maximum value weight value, so that we can indicate which point to select. Then consider how not to intersect, the source company to the point of horizontal shooting, the point of vertical shooting to join. After that, we use the idea similar to cake cutting to divide each intersection into two horizontal and vertical points, connecting inf between them, so as to ensure that a weight will be selected before this intersection, and only one shooting tower will be selected.
The best part is to use the maximum value to solve this problem.

#include <bits/stdc++.h>
using namespace std;
const int maxn = 55, maxp = 55 * 55 * 3, inf = 1e9;
struct edge {
    int nxt, to, f;
} e[2000005];
const int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
#define id(x, y, z) z * n * m + (x - 1) * m + y
int n, m, ans, cnt = 1, source, sink;
int h[maxp], iter[maxp], d[maxp], a[maxn][maxn];
void link(int u, int v, int f) {
    e[++cnt].nxt = h[u];
    h[u] = cnt;
    e[cnt].to = v;
    e[cnt].f = f;
}
void insert(int u, int v, int f) {
    link(u, v, f);
    link(v, u, 0);
}
bool bfs() {
    queue<int> q;
    q.push(source);
    memset(d, -1, sizeof(d));
    d[source] = 0;
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(int i = h[u]; i; i = e[i].nxt) {
            if(d[e[i].to] == -1 && e[i].f) {
                d[e[i].to] = d[u] + 1;
                q.push(e[i].to);
            }
        }
    }
    return d[sink] != -1;
}
int dfs(int u, int delta) {
    if(u == sink) {
        return delta;
    }
    int ret = 0;
    for(int &i = iter[u]; i; i = e[i].nxt) {
        if(d[e[i].to] == d[u] + 1 && e[i].f) {
            int x = dfs(e[i].to, min(delta, e[i].f));
            e[i].f -= x;
            e[i ^ 1].f += x;
            delta -= x;
            ret += x;
            if(!delta) {
                break;
            }
        }
    }
    return ret;
} 
int dinic() {
    int ret = 0;
    while(bfs()) {
        for(int i = source; i <= sink; ++i) {
            iter[i] = h[i];
        }
        ret += dfs(source, inf);
    }
    return ret;
}
int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= m; ++j) {
            scanf("%d", &a[i][j]);
        }
    }
    sink = n * m * 2 + 1;
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= m; ++j) {
            if(a[i][j] < 0) {
                int mx = 0, x = i, y = j, t = -a[i][j] - 1;
                while(1) {
                    x += dx[t];
                    y += dy[t];
                    if(x < 1 || x > n || y < 1 || y > m) {
                        break;
                    }
                    mx = max(mx, a[x][y]);
                }
                ans += mx;
                if(t < 2) {
                    insert(source, id(i, j, 0), inf);
                } else {
                    insert(id(i, j, 1), sink, inf);
                }
                x = i;
                y = j;
                while(1) {
                    int xx = x, yy = y;
                    x += dx[t];
                    y += dy[t];
                    if(x < 1 || x > n || y < 1 || y > m) {
                        break;
                    }
                    if(t < 2) {
                        insert(id(xx, yy, 0), id(x, y, 0), mx - max(0, a[xx][yy]));
                    } else {
                        insert(id(x, y, 1), id(xx, yy, 1), mx - max(0, a[xx][yy]));
                    }
                }
            } else {
                insert(id(i, j, 0), id(i, j, 1), inf);
            }
        }
    }
    printf("%d\n", ans - dinic());
    return 0;
}

Topics: network