P2045 方格取数加强版 最大费用最大流
$ \color{#0066ff}{ 题目描述 }$
给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,这样一共走K次,现在要求K次所达到的方格的数的和最大
\(\color{#0066ff}{输入格式}\)
第一行两个数n,k(1<=n<=50, 0<=k<=10)
接下来n行,每行n个数,分别表示矩阵的每个格子的数
\(\color{#0066ff}{输出格式}\)
一个数,为最大和
\(\color{#0066ff}{输入样例}\)
3 1
1 2 3
0 2 1
1 4 2
\(\color{#0066ff}{输出样例}\)
11
\(\color{#0066ff}{数据范围与提示}\)
每个格子中的数不超过1000
\(\color{#0066ff}{题解}\)
拆点,矩阵每个元素拆成入点和出点
入点向出点连容量为1, 权值为点权的边,代表只能选一次
入点再向出点连容量为inf,权值为0的边,代表之后也能走这个格子,但是无法获得权值
最大费用最大流即可(这里用了ZKWqwq)
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int inf = 0x7fffffff;
const int maxn = 1e5 + 10;
struct node {
int to, can, dis;
node *nxt, *rev;
node(int to = 0, int can = 0, int dis = 0, node *nxt = NULL): to(to), can(can), dis(dis), nxt(nxt) {
rev = NULL;
}
};
node *head[maxn];
bool vis[maxn];
int dis[maxn], mp[100][100];
int n, k, s, t;
void add(int from, int to, int can, int dis) {
head[from] = new node(to, can, dis, head[from]);
}
void link(int from, int to, int can, int dis) {
add(from, to, can, dis);
add(to, from, 0, -dis);
head[from]->rev = head[to];
head[to]->rev = head[from];
}
bool spfa() {
for(int i = s; i <= t; i++) vis[i] = false, dis[i] = -inf;
std::deque<int> q;
q.push_back(t);
dis[t] = 0;
while(!q.empty()) {
int tp = q.front(); q.pop_front();
vis[tp] = false;
for(node *i = head[tp]; i; i = i->nxt) {
if(dis[i->to] < dis[tp] - i->dis && i->rev->can) {
dis[i->to] = dis[tp] - i->dis;
if(!vis[i->to]) {
if(!q.empty() && dis[i->to] > dis[q.front()]) q.push_front(i->to);
else q.push_back(i->to);
vis[i->to] = true;
}
}
}
}
return dis[s] != -inf;
}
int dfs(int x, int change) {
if(x == t || !change) return change;
int flow = 0, ls;
vis[x] = true;
for(node *i = head[x]; i; i = i->nxt) {
if(!vis[i->to] && dis[i->to] == dis[x] - i->dis && (ls = dfs(i->to, std::min(change, i->can)))) {
flow += ls;
change -= ls;
i->can -= ls;
i->rev->can += ls;
if(!change) break;
}
}
return flow;
}
int zkw() {
int cost = 0;
while(spfa()) {
vis[t] = true;
while(vis[t]) {
for(int i = s; i <= t; i++) vis[i] = false;
cost += dis[s] * dfs(s, inf);
}
}
return cost;
}
int id(int x, int y) { return (x - 1) * n + y; }
int main() {
n = in(), k = in();
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
mp[i][j] = in();
s = 0, t = 2 * n * n + 1;
link(s, id(1, 1), k, 0);
link(id(n, n) + n * n, t, k, 0);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) {
if(i + 1 <= n) link(n * n + id(i, j), id(i + 1, j), inf, 0);
if(j + 1 <= n) link(n * n + id(i, j), id(i, j + 1), inf, 0);
link(id(i, j), n * n + id(i, j), 1, mp[i][j]);
link(id(i, j), n * n + id(i, j), inf, 0);
}
printf("%d", zkw());
return 0;
}
P2045 方格取数加强版 最大费用最大流的更多相关文章
- 洛谷 P2045 方格取数加强版【费用流】
题目链接:https://www.luogu.org/problemnew/show/P2045 题目描述 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现 ...
- P2045 方格取数加强版
P2045 方格取数加强版 题目描述 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格 ...
- bzoj P2045 方格取数加强版【最大费用最大流】
今天脑子不太清醒,把数据范围看小了一直TTTTLE-- 最大费用最大流,每个格子拆成两个(x,y),(x,y)',(x,y)向(x,y)'连一条费用a[x][y]流量1的边表示选的一次,再连一条费用0 ...
- 洛谷P2045 方格取数加强版(费用流)
题意 题目链接 Sol 这题能想到费用流就不难做了 从S向(1, 1)连费用为0,流量为K的边 从(n, n)向T连费用为0,流量为K的边 对于每个点我们可以拆点限流,同时为了保证每个点只被经过一次, ...
- 【Luogu】P2045方格取数加强版(最小费用最大流)
题目链接 通过这题我学会了引诱算法的行为,就是你通过适当的状态设计,引诱算法按照你想要它做的去行动,进而达到解题的目的. 最小费用最大流,首先将点拆点,入点和出点连一条费用=-权值,容量=1的边,再连 ...
- [洛谷P2045]方格取数加强版
题目大意:有一个n*n的矩阵,每个格子有一个非负整数,规定一个人从(1,1)开始,只能往右或下走,走到(n,n)为止,并把沿途的数取走,取走后数变为0.这个人共取n次,求取得的数的最大总和. 解题思路 ...
- [CodeVs1227]方格取数2(最大费用最大流)
网络流24题的坑还没填完,真的要TJ? 题目大意:一个n*n的矩阵,每格有点权,从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,这样一共走 ...
- 洛谷 - P2045 - 方格取数加强版 - 费用流
原来这种题的解法是费用流. 从一个方格的左上走到右下,最多走k次,每个数最多拿走一次. 每次走动的流量设为1,起始点拆点成限制流量k. 每个点拆成两条路,一条路限制流量1,费用为价值相反数.另一条路无 ...
- 洛谷P2045 方格取数加强版 最小费用流
Code: #include<cstdio> #include<cstring> #include<algorithm> #include<queue> ...
随机推荐
- class function
type TTest = class public class function sayHello :String; function saybye:String; ...
- Python基础学习四 函数
1.内置函数 Python内置了很多有用的函数,是可以直接调用的. 参考链接:https://docs.python.org/3/library/functions.html 调用函数的时候,如果传入 ...
- 设备控制接口ioctl详解
[转]Linux设备控制接口 序言设备驱动程序的一个基本功能就是管理和控制设备,同时为用户应用程序提供管理和控制设备的接口.我们前面的“Hello World”驱动程序已经可以提供读写功能了,在这里我 ...
- AngularJS学习(一)
参考文章:http://blog.csdn.net/dc_726/article/details/17010325 1.HelloWorld篇 1.1 环境 下载:angular-1.2.5min.j ...
- random和os模块
一.random模块 常用方法如下: #-*- coding:utf-8 -*- import random print(random.randint(1,100)) # 获取一个范围内的随机数,包含 ...
- Linux的基本指令--服务器
ftp: 1.安装vsftpd服务器 sudo apt-get install vsftpd 2.创建一个空目录,供用户上传:创建服务器文件夹,ftp服务器,服务器端和客户端,我建立的是/home/c ...
- 构造方法概念,自定义构造(init)方法的用途, 类工厂方法(就是直接用类名 类调用)
一. 构造方法 构造方法:在OC中init开头的方法, 我们称之为构造方法 构造方法的用途: 用于初始化一个对象, 让某个对象一创建出来就拥有某些属性和值 // 比如我们定义一个Person的类,然后 ...
- ubuntu16.04 Mask_RCNN AlphaPose OpenPose Librealsense
#############MaskRCNNcource activate flappbirdcd /home/luo/Desktop/MyFile/MaskRCNN/MyOwnMaskRCNN1/sa ...
- Auto Control 001 自动控制的一般概念
自动控制的基本概念 一 . 自动控制系统的组成 自动控制装置:自动控制装置的组成当中涉及到了这样这样一些东西: 第1,需要有被控对象,那么这些被控对象需要有谁来控制呢?一定要有控制器,这些控制器,我们 ...
- codefirst 最新策略
http://www.yunjuu.com/info/76058.html 在原有数据库中使用 CodeFirst ,除了第一次添加实体后要立即执行一次 Enable-Migrations add-m ...