luogu4012 深海机器人问题 网络流
关键词:最小费用最大流
题目大意:海底是个网格,每个网格边有一定价值的海底化石。每个路线可经过无限个机器人,但上面的化石只能采一次。机器人可沿网格边向东或向北移动。给定机器人起点和终点位置及所能容纳的机器人数,求能获得的最大价值。
网络流:把一个机器人运动的轨迹看作一个流量为1的流。
化石只能采一次,我们想到建立一条容量为1的边,价值为-化石价值。以后该路线可经过无限个机器人,我们想到建立一条容量为∞的边,价值为0。S连起点,终点连T,容量为其所能容纳的机器人数。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cassert>
using namespace std; #define LOOP(i, n) for(int i=1; i<=n; i++)
#define ID(col, row) row * (lastCol + 1) + col + 1
const int MAX_NODE = * , MAX_EDGE = MAX_NODE*MAX_NODE * , INF = 0x3f3f3f3f, MAX_ROW = , MAX_COL = ; struct MCMF
{
struct Node;
struct Edge; struct Node
{
Edge *Head, *Prev;
int Dist, Id;
bool Inq;
}; struct Edge
{
int Cap, Cost, OrgCap;
Node *From, *To;
Edge *Next, *Rev;
Edge(int cap, int cost, Node *from, Node *to, Edge *next) :Cap(cap), OrgCap(cap), Cost(cost), From(from), To(to), Next(next) {}
}; Node _nodes[MAX_NODE];
Edge *_edges[MAX_EDGE];
int _vCount = , _eCount = ;
Node *Start, *Sink;
int TotFlow, TotCost; void Init(int n, int sId, int tId)
{
_vCount = n;
_eCount = ;
Start = &_nodes[sId], Sink = &_nodes[tId];
TotFlow = TotCost = ;
} Edge* AddEdge(Node *from, Node *to, int cap, int cost)
{
Edge *e = _edges[++_eCount] = new Edge(cap, cost, from, to, from->Head);
e->From->Head = e;
return e;
} void Build(int uId, int vId, int cap, int cost)
{
//printf("%d->%d\n", uId, vId);
Node *u = uId + _nodes, *v = vId + _nodes;
u->Id = uId;
v->Id = vId;
Edge *edge1 = AddEdge(u, v, cap, cost), *edge2 = AddEdge(v, u, , -cost);
edge1->Rev = edge2;
edge2->Rev = edge1;
} bool SPFA()
{
queue<Node*> q;
LOOP(i, _vCount)
{
_nodes[i].Prev = NULL;
_nodes[i].Dist = INF;
_nodes[i].Inq = false;
}
Start->Dist = ;
q.push(Start);
while (!q.empty())
{
Node *u = q.front();
q.pop();
u->Inq = false;
for (Edge *e = u->Head; e; e = e->Next)
{
if (e->Cap && u->Dist + e->Cost < e->To->Dist)
{
e->To->Dist = u->Dist + e->Cost;
e->To->Prev = e;
if (!e->To->Inq)
{
e->To->Inq = true;
q.push(e->To);
}
}
}
}
return Sink->Prev;
} void Proceed()
{
while (SPFA())
{
assert(Sink->Dist != INF);
int minFlow = INF;
for (Edge *e = Sink->Prev; e; e = e->From->Prev)
minFlow = min(minFlow, e->Cap);
TotFlow += minFlow;
for (Edge *e = Sink->Prev; e; e = e->From->Prev)
{
e->Cap -= minFlow;
e->Rev->Cap += minFlow;
TotCost += minFlow * e->Cost;
}
}
}
}g; int main()
{
#ifdef _DEBUG
freopen("c:\\noi\\source\\input.txt", "r", stdin);
#endif
int totStart, totTarget, lastCol, lastRow,
row, col, horiVal, vertVal, robotCnt;
scanf("%d%d%d%d", &totStart, &totTarget, &lastRow, &lastCol);
int sId = ID(lastCol, lastRow) + , tId = ID(lastCol, lastRow) + ;
g.Init(tId, sId, tId);
for (int row = ; row <= lastRow; row++)
for (int col = ; col <= lastCol; col++)
{
scanf("%d", &horiVal);
g.Build(ID((col - ), row), ID(col, row), INF, );
g.Build(ID((col - ), row), ID(col, row), , -horiVal);
}
for (int col = ; col <= lastCol; col++)
for (int row = ; row <= lastRow; row++)
{
scanf("%d", &vertVal);
g.Build(ID(col, (row - )), ID(col, row), INF, );
g.Build(ID(col, (row - )), ID(col, row), , -vertVal);
}
LOOP(i, totStart)
{
scanf("%d%d%d", &robotCnt, &row, &col);
g.Build(sId, ID(col, row), robotCnt, );
}
LOOP(i, totTarget)
{
scanf("%d%d%d", &robotCnt, &row, &col);
g.Build(ID(col, row), tId, robotCnt, );
}
g.Proceed();
printf("%d\n", -g.TotCost);
return ;
}
注意:宏替换写函数时,对其所操作的参数尽量打括号,否则会出现运算顺序问题。
luogu4012 深海机器人问题 网络流的更多相关文章
- 【网络流24题】No. 20 深海机器人问题 (费用流)
[题意] 深海资源考察探险队的潜艇将到达深海的海底进行科学考察.潜艇内有多个深海机器人. 潜艇到达深海海底后, 深海机器人将离开潜艇向预定目标移动. 深海机器人在移动中还必须沿途采集海底生物标本. 沿 ...
- 【刷题】LOJ 6224 「网络流 24 题」深海机器人问题
题目描述 深海资源考察探险队的潜艇将到达深海的海底进行科学考察. 潜艇内有多个深海机器人.潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动. 深海机器人在移动中还必须沿途采集海底生物标本.沿途生 ...
- 【PowerOJ1755&网络流24题】深海机器人问题(费用流)
题意: 思路: [问题分析] 最大费用最大流问题. [建模方法] 把网格中每个位置抽象成网络中一个节点,建立附加源S汇T. 1.对于每个顶点i,j为i东边或南边相邻的一个节点,连接节点i与节点j一条容 ...
- [洛谷P4012] [网络流24题] 深海机器人问题
Description 深海资源考察探险队的潜艇将到达深海的海底进行科学考察. 潜艇内有多个深海机器人.潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动. 深海机器人在移动中还必须沿途采集海底生 ...
- (luogu P4012)深海机器人问题 [TPLY]
网页链接 https://www.luogu.org/problemnew/show/4012 做题背景 在不久的将来,人工智能发展使得人类大量失业,也使得现在的我们做[深海机器人问题]做得想死... ...
- 洛谷 P4012 深海机器人问题【费用流】
题目链接:https://www.luogu.org/problemnew/show/P4012 洛谷 P4012 深海机器人问题 输入输出样例 输入样例#1: 1 1 2 2 1 2 3 4 5 6 ...
- luogu P4012 深海机器人问题
luogu P4012 深海机器人问题 // luogu-judger-enable-o2 #include<queue> #include<cstdio> #include& ...
- P4012 深海机器人问题
\(\color{#0066ff}{题目描述}\) 深海资源考察探险队的潜艇将到达深海的海底进行科学考察. 潜艇内有多个深海机器人.潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动. 深海机器人 ...
- 深海机器人(cogs 742)
«问题描述:深海资源考察探险队的潜艇将到达深海的海底进行科学考察.潜艇内有多个深海机器人.潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动.深海机器人在移动中还必须沿途采集海底生物标本.沿途生物 ...
随机推荐
- 牛客练习赛19 -E-托米的饮料
题目描述 好了,现在是小托米的故事啦~~~ 可爱的小托米得到了n瓶饮料. 但他不小心把开盖的工具弄丢了,所以他只能利用饮料瓶来开盖. 已知第i个瓶子的品牌为ai,且其能打开bi品牌的瓶子. 问有几瓶饮 ...
- C#中通过js实现个人用户和非个人用户的登陆
实现用户的登录功能,这里举一个个人和非个人用户的登录的例子 前台代码: <ul class="login_list clearfix"> <li> < ...
- (转)vuex2.0 基本使用(3) --- getter
有的组件中获取到 store 中的state, 需要对进行加工才能使用,computed 属性中就需要写操作函数,如果有多个组件中都需要进行这个操作,那么在各个组件中都写相同的函数,那就非常麻烦,这 ...
- 【python】数组去重
直接用set就行,比如: l = [1, 1, 2, 2, 3, 4, 5] s = set(l) c = [i for i in s] print c 结果为: [1, 2, 3, 4, 5] 其中 ...
- SLAM: 图像角点检测的Fast算法(OpenCV文档)
官方链接:http://docs.opencv.org/trunk/doc/py_tutorials/py_feature2d/py_fast/py_fast.html#fast-algorithm- ...
- 利用node、express初始化项目
前端做整站是开发,例如:前端是用了vue创建初始化项目,后端我们不会php.java等,我们只能用node去创建去做后端代码,本文就给大家讲解最基础的从零开始创建一个项目的后端环境. 一般来说前后端代 ...
- 【转载】java的常见类型转换
//Int型数字转换成String int num1=123456; //方法1 String str1=num1+""; System.out.println(str1); // ...
- 【转载】java实现HTTP请求的三种方式
目前JAVA实现HTTP请求的方法用的最多的有两种:一种是通过HTTPClient这种第三方的开源框架去实现.HTTPClient对HTTP的封装性比较不错,通过它基本上能够满足我们大部分的需求,Ht ...
- mysql字符集和排序规则
1.关于字符集和排序规则所为字符集,就是用来定义字符在数据库中的编码的集合.常见的字符集有:utf8(支持中文)和AccIS(不支持中文) 数据库中的排序规则用来定义字符在进行排序和比较的时候的一种规 ...
- struts2中<jsp:forward>跳转时报404错误的问题
index.jsp页面: <jsp:forward page="show.action"></jsp:forward> 在struts.x ...