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
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;
}