bzoj4657(tc SRM627 div1 T3):tower(网络流)

Description
Nick最近在玩一款很好玩的游戏,游戏规则是这样的:
有一个n*m的地图,地图上的每一个位置要么是空地,要么是炮塔,要么是一些BETA狗,Nick需
要操纵炮塔攻击BETA狗们。
攻击方法是:对于每个炮塔,游戏系统已经给出它可以瞄准的方向(上下左右其中一个),Nick需要
选择它的攻击位置,每一个炮塔只能够攻击一个位置,炮塔只能够向着它的瞄准方向上的某个位置发
动攻击,当然炮塔也可以不进行攻击。炮塔威力强大,它可以且仅可以消灭目标位置上所有的BETA狗。
出于安全考虑,游戏系统已经保证不存在一个炮塔能够瞄准另外一个炮塔,即对于任意一个炮
塔,它所有可能的攻击位置上不存在另外一个炮塔。而且,如果把炮塔的起点和终点称为炮弹的运行
轨迹,那么系统不允许两条轨迹相交f包括起点和终点)。
现在,选定目标位置以后,每一个炮塔同时开炮,你要告诉Nick,他最多可以干掉多少BETA狗。
Input
第一行两个正整数n,m,表示地图的规模。
接下来礼行,每行m个整数,0表示空地,-1,-2,一3,-4分别表示瞄准上下左右的炮塔,若为正整
数p,则表示该位置有p个BETA狗。
n,m <= 50,每个位置的BETA狗数量不超过999个,保证不存在任意一个炮塔能够瞄准另外一个炮塔
Output
一个正整数,表示Nick最多可以干掉几个BETA狗
Sample Input
3 2
0 9
-4 3
0 -1
Sample Output
9


矛盾肯定是横的和竖的之间的
可以看做一条竖的到横的的路径
考虑最小割

直接连边,边权为割掉这条边能获得的最大权值
同时对每个点拆点防止多次转弯

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define ll long long
#define pb push_back
#define SZ(x) ((int)(x.size()))
void gi(int &sum){
    sum = 0;char c = getchar();bool flag = true;
    while(c < '0' || c > '9') {if(c == '-') flag = false;c = getchar();}
    while(c >= '0' && c <= '9') sum = sum * 10 + c - 48,c = getchar();
    if(!flag) sum = -sum;
}
const int oo = 1e7;
int n,m;
char Map[60][60],g[5] = {'.','A','V','<','>'};
int v[60][60],spe[60][60];
int id[2][60][60],tot;
int S,T;
int linkk[10100],t,ans,dep[10100];
struct node{int n,y,v;}e[201000];
queue<int>q;
void insert(int x,int y,int z){
    e[++t].y = y;e[t].n = linkk[x];e[t].v = z;linkk[x] = t;
    e[++t].y = x;e[t].n = linkk[y];e[t].v = 0;linkk[y] = t;
}
int cas;
void pre(){
    int en,t;
    vector<int>h;
    rep(i,1,n) rep(j,1,m){
        if(spe[i][j] == 3){
            en = j; h.clear(); h.pb(j);
            repp(k,j-1,1) if(spe[i][k] != 0) break;
            else{
                en = k;
                if(v[i][k] > v[i][ h[SZ(h)-1 ] ]) h.pb(k);
            }
            t = SZ(h)-1; ans += v[i][h[t]];
            rep(k,en,j-1){
                while(t>=0 && h[t] <= k) t--;
                insert( id[1][i][k] , id[1][i][k+1] , t == SZ(h)-1?0:v[i][h[SZ(h)-1]] - v[i][h[t]] );
            }
        }
        else if(spe[i][j] == 4) {
            en = j; h.clear(); h.pb(j);
            rep(k,j+1,m) if(spe[i][k] != 0) break;
            else{
                en = k;
                if(v[i][k] > v[i][ h[SZ(h)-1] ]) h.pb(k);
            }
            t = SZ(h)-1; ans += v[i][h[t]];
            repp(k,en,j+1){
                while(t>=0 && h[t] >= k) t--;
                insert( id[1][i][k] , id[1][i][k-1] , t == SZ(h)-1?0:v[i][h[SZ(h)-1]] - v[i][h[t]] );
            }
        }
        else if(spe[i][j] == 1){
            en = i; h.clear(); h.pb(i);
            repp(k,i-1,1) if(spe[k][j] != 0) break;
            else{
                en = k;
                if(v[k][j] > v[ h[SZ(h)-1] ][j]) h.pb(k);
            }
            t = SZ(h)-1; ans += v[h[t]][j];
            rep(k,en,i-1){
                while(t>=0 && h[t] <= k) t--;
                insert( id[0][k+1][j] , id[0][k][j] , t == SZ(h)-1?0:v[h[SZ(h)-1]][j] - v[h[t]][j] );
            }
        }
        else if(spe[i][j] == 2){
            en = i; h.clear(); h.pb(i);
            rep(k,i+1,n) if(spe[k][j] != 0) break;
            else {
                en = k;
                if(v[k][j] > v[ h[SZ(h)-1] ][j]) h.pb(k);
            }
            t = SZ(h)-1; ans += v[h[t]][j];
            repp(k,en,i+1){
                while(t>=0 && h[t] >= k) t--;
                insert( id[0][k-1][j] , id[0][k][j] , t == SZ(h)-1?0:v[h[SZ(h)-1]][j] - v[h[t]][j] );
            }
        }
    }
}
bool bfs(){
    rep(i,1,tot) dep[i] = -1; dep[S] = 0; q.push(S);
    while(!q.empty()){
        int x = q.front();q.pop();
        for(int i = linkk[x];i;i = e[i].n) 
            if(e[i].v && dep[e[i].y] == -1) dep[e[i].y] = dep[x] + 1,q.push(e[i].y);
    }
    return dep[T] != -1;
}
int dinic(int x,int lazy){
    if(x == T) return lazy;
    int d = 0,nowlazy = 0;
    for(int i = linkk[x];i && nowlazy < lazy;i = e[i].n)
        if(e[i].v && dep[e[i].y] == dep[x] + 1)
            if( ( d = dinic(e[i].y,min(e[i].v,lazy-nowlazy)) ) ){
                nowlazy += d;
                e[i].v -= d;
                e[i^1].v += d;
            }
    if(nowlazy == 0) dep[x] = -1;
    return nowlazy;
}
int main(){
    gi(n); gi(m);
    rep(i,1,n) rep(j,1,m) {
    	gi(v[i][j]);
    	if(v[i][j] < 0) spe[i][j] = abs(v[i][j]) , v[i][j] = 0;
	}
	rep(i,1,n) rep(j,1,m) id[0][i][j] = ++tot,id[1][i][j] = ++tot;
    S = ++tot; T = ++tot; t = 1;
    pre();
    rep(i,1,n) rep(j,1,m) 
        if(spe[i][j] == 1 || spe[i][j] == 2) insert(S,id[0][i][j],oo);
        else if(spe[i][j] == 3 || spe[i][j] == 4) insert(id[1][i][j],T,oo);
    rep(i,1,n) rep(j,1,m) insert(id[0][i][j],id[1][i][j],oo);
    while(bfs()) ans -= dinic( S , oo );
    printf("%d\n",ans);
    return ans;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值