4657: tower
来源:互联网 发布:汽车can网络是什么 编辑:程序博客网 时间:2024/05/16 15:30
4657: tower
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 59 Solved: 28
[Submit][Status][Discuss]
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
0 9
-4 3
0 -1
Sample Output
9
HINT
Source
对于每个纵向发射的炮弹,定义它的方向是从炮台出发到目标
对于每个横向发射的炮弹,定义它的方向是从目标出发到炮台
考虑两条相交的炮弹轨迹,就能画成这样的形式
那么就可以看成一条x->y的路径
所以一个合法的方案必然不存在任何这样的路径
先将每条路径上最大的BETA狗数量统计出来,加起来作为答案
考虑使用最小割将不合法的路径剔除
对于一条有向边(u,v),如果割掉它,就当做让炮塔攻击了点u
那么每个纵向炮塔向出发的方向连边,每个横向炮塔向进入的方向连边
不过这样会出现一个小BUG
此图虽然出现了一条x->y的路径,但是有一个合法方案可以与之对应,即每个点都打到面前的板上
出现这种情况的原因,是这条路径连续拐了两个弯,那么不允许出现连续拐两个弯的局面
把原图中每个点拆成纵点和横点,每个纵点向对应的横点连INF的边
纵点和纵点之间,横点和横点之间再连边即可
#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<algorithm>#include<cmath>#include<stack>#define min(a,b) ((a) < (b) ? (a) : (b))#define max(a,b) ((a) > (b) ? (a) : (b))using namespace std; const int maxn = 5050;const int INF = ~0U>>1;const int maxm = 4E5 + 40;const int dx[4] = {-1,1,0,0};const int dy[4] = {0,0,-1,1}; struct E{ int to,cap,flow; E(){} E(int to,int cap,int flow): to(to),cap(cap),flow(flow){}}edgs[maxm]; int n,m,tot,s,t,Ans,cnt,A[55][55],B[55][55],w[55][55],cur[maxn],L[maxn]; queue <int> Q;vector <int> v[maxn]; inline void Add(int x,int y,int cap){ v[x].push_back(cnt); edgs[cnt++] = E(y,cap,0); v[y].push_back(cnt); edgs[cnt++] = E(x,0,0);} void Build(){ for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { if (w[i][j] >= 0) continue; int dir = -(w[i][j] + 1),Max = w[i][j] = 0; for (int x = i + dx[dir],y = j + dy[dir]; ;) { if (x < 1 || x > n || y < 1 || y > m) break; Max = max(Max,w[x][y]); x += dx[dir]; y += dy[dir]; } Ans += Max; if (dir <= 1) { Add(s,A[i][j],INF); for (int x = i + dx[dir],y = j + dy[dir]; ;) { if (x < 1 || x > n || y < 1 || y > m) break; Add(A[x - dx[dir]][y - dy[dir]],A[x][y],Max - w[x - dx[dir]][y - dy[dir]]); x += dx[dir]; y += dy[dir]; } } else { Add(B[i][j],t,INF); for (int x = i + dx[dir],y = j + dy[dir]; ;) { if (x < 1 || x > n || y < 1 || y > m) break; Add(B[x][y],B[x - dx[dir]][y - dy[dir]],Max - w[x - dx[dir]][y - dy[dir]]); x += dx[dir]; y += dy[dir]; } } }} inline bool BFS(){ for (int i = 1; i <= tot; i++) L[i] = 0; L[s] = 1; Q.push(s); while (!Q.empty()) { int k = Q.front(); Q.pop(); for (int i = 0; i < v[k].size(); i++) { E e = edgs[v[k][i]]; if (e.cap == e.flow || L[e.to]) continue; L[e.to] = L[k] + 1; Q.push(e.to); } } return L[t];} inline int Dinic(int x,int a){ if (x == t) return a; int flow = 0; for (int &i = cur[x]; i < v[x].size(); i++) { E &e = edgs[v[x][i]]; if (e.cap == e.flow || L[e.to] != L[x] + 1) continue; int f = Dinic(e.to,min(a,e.cap - e.flow)); if (!f) continue; flow += f; e.flow += f; edgs[v[x][i]^1].flow -= f; a -= f; if (!a) return flow; } if (!flow) L[x] = -1; return flow;} int main(){ #ifdef DMC freopen("DMC.txt","r",stdin); #endif cin >> n >> m; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { A[i][j] = ++tot; B[i][j] = ++tot; scanf("%d",&w[i][j]); Add(A[i][j],B[i][j],INF); } s = ++tot; t = ++tot; Build(); int MinCut = 0; while (BFS()) { for (int i = 1; i <= tot; i++) cur[i] = 0; MinCut += Dinic(s,INF); } cout << Ans - MinCut << endl; return 0;}
0 0
- 4657: tower
- BZOJ 4657: tower
- Tower
- tower
- bzoj 4657: tower 最小割
- Ivory Tower
- hdu2971 Tower
- [DP]Tower
- 【计数】tower
- hannuo tower
- Hanoi Tower
- Hanoi Tower
- 【bzoj4352】 Tower
- Hanoi Tower
- Bzoj4352 Tower
- Dwarf tower
- dwarf tower
- dwarf tower
- 编程练习之字符串连接的最长路径查找
- ubuntu caffe opencv pip
- cogs 740. [网络流24题] 分配问题
- 大数计算
- C++之虚函数表解析
- 4657: tower
- git常用命令
- android 用户登录及记录密码功能
- 在python3.5和django1.10.6的环境下使用xadmin
- 装备选择
- Linux入门(一) 之 安装Linux操作系统
- 校赛选拔之 离散化+ 双指针+思维
- 关于异常
- 并发和负载在高性能协议中的应用