Description

给出一个 \(n*n\) 的矩阵,每一格有一个非负整数 \(A_{i,j}\) ,(\(A_{i,j} <= 1000\))现在从 \((1,1)\) 出发,可以往右或者往下走,最后到达 \((n,n)\) ,每达到一格,把该格子的数取出来,该格子的数就变成 \(0\) ,这样一共走 \(K\) 次,现在要求 \(K\) 次所达到的方格的数的和最大

Solution

一条边 \((a,b)\) 表示容量为 \(a\) ,费用为 \(b\) 。

把每个点拆成两个点,入点和出点。入点用来接受边,出点用来发出边

源点向 \((1,1)\) 连一条边 \((k,0)\) ,\((n,n)\) 向汇点连一条 \((k,0)\) ,表示可以走 \(k\) 次

每个点往他的右和下分别连一条 \((\infty, 0)\) 表示联通关系

每个点的入点与出点之间连两条边 \((1,x)\) 和 \((\infty, 0)\)。\(x\) 是该点的权值。

这是因为每个点只能取一次。

然后跑一遍最大费用最大流就完事啦

小技巧:把费用取负然后跑最小费用最大流

Code

#include <bits/stdc++.h>
using namespace std;
const int INF = 1000000000;
const int N = 550;
int n, m, cnt, vis[N * N * 3], dis[N * N * 3];
int S, T, k, pre[N * N * 3], f[N * N * 3];
struct node {
int d, sid, tid;
}a[N][N];
struct edge {
int v, w, f; edge *next, *rev;
}pool[N * N * 2], *head[N * N * 3], *r[N * N * 3];
inline void addedge(int u, int v, int f, int w) {
edge *p = &pool[++cnt], *q = &pool[++cnt];
p->v = v, p->f = f, p->w = w, p->next = head[u], head[u] = p; p->rev = q;
q->v = u, q->f = 0, q->w = -w, q->next = head[v], head[v] = q; q->rev = p;
}
inline bool spfa() {
for(int i = S; i <= T; i++) r[i] = NULL, dis[i] = INF, vis[i] = 0, pre[i] = -1;
queue <int> Q; Q.push(S); vis[S] = 1; dis[S] = 0; f[S] = INF;
while(!Q.empty()) {
int u = Q.front(); Q.pop(); vis[u] = 0;
for(edge *p = head[u]; p; p = p->next) {
int v = p->v;
if(p->f > 0 && dis[v] > dis[u] + p->w) {
dis[v] = dis[u] + p->w;
pre[v] = u, r[v] = p;
f[v] = min(f[u], p->f);
if(!vis[v]) vis[v] = 1, Q.push(v);
}
}
}
return pre[T] != -1;
}
inline int MCMF() {
int ans = 0;
while(spfa()) {
for(int i = T; i != S; i = pre[i]) {
r[i]->f -= f[T]; r[i]->rev->f += f[T];
} ans += dis[T] * f[T];
} return ans;
}
int main() {
scanf("%d %d", &n, &k); S = 0, T = 2 * n * n + 1;
addedge(S, 1, k, 0);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
int x; scanf("%d", &x);
int id = (i - 1) * n + j;
a[i][j].sid = 2 * id - 1;
a[i][j].tid = 2 * id;
addedge(a[i][j].sid, a[i][j].tid, 1, -x);
addedge(a[i][j].sid, a[i][j].tid, INF, 0);
}
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) {
if(i < n) addedge(a[i][j].tid, a[i + 1][j].sid, INF, 0);
if(j < n) addedge(a[i][j].tid, a[i][j + 1].sid, INF, 0);
}
addedge(a[n][n].tid, T, k, 0);
printf("%d\n", -MCMF());
return 0;
}

题解【luogu2045 方格取数游戏加强版】的更多相关文章

  1. Luogu2045 方格取数加强版

    题目描述 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变 ...

  2. Luogu2045 方格取数加强版(K取方格数) 费用流

    题目传送门 题意:给出一个$N \times N$的方格,每个格子中有一个数字.你可以取$K$次数,每次取数从左上角的方格开始,每一次只能向右或向下走一格,走到右下角结束,沿路的方格中的数字将会被取出 ...

  3. 【P2405】方格取数问题加强版(费用流)

    考虑如何建图.还是老样子先拆点,然后把每两个点之间连接两条边,一条流量为1,费用为-点权,处理是否走这个点.一条流量无限,没有费用,因为哪怕一个点选过了,它的地方还是可以重复走过去的. 然后把经由一个 ...

  4. 题解 P1004 方格取数

    传送门 动态规划Yes? 设i为路径长度,(为什么i这一维可以省掉见下)f[j][k]表示第一个点到了(j,i-j),第二个点到了(k,j-k) 则 int ji=i-j,ki=i-k; f[j][k ...

  5. [luogu_P2045]方格取数加强版

    [luogu_P2045]方格取数加强版 试题描述 给出一个 \(n \times n\) 的矩阵,每一格有一个非负整数 \(A_{i,j},(A_{i,j} \le 1000)\) 现在从 \((1 ...

  6. 棋盘DP三连——洛谷 P1004 方格取数 &&洛谷 P1006 传纸条 &&Codevs 2853 方格游戏

    P1004 方格取数 题目描述 设有N $\times N$N×N的方格图(N $\le 9$)(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字00.如下图所示(见样例): A ...

  7. P2045 方格取数加强版

    P2045 方格取数加强版 题目描述 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格 ...

  8. 洛谷 P1004 方格取数 题解

    P1004 方格取数 题目描述 设有 \(N \times N\) 的方格图 \((N \le 9)\),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字\(0\).如下图所示(见样例): ...

  9. HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]

    题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...

随机推荐

  1. Java 学习笔记 ------第三章 基础语法

    本章学习目标: 认识类型与变量 学习运算符的基本使用 了解类型转换细节 运用基本流程语法 一.类型(基本类型) 所谓基本类型,就是在使用时,得考虑一下数据用多少内存长度存比较经济,利用程序语法告诉JV ...

  2. 对其中的一个特点将NABC的分析结果

    一.题目要求 每一个组员针对其中的一个特点将NABC的分析结果发表博客上(截止日期4月8日晚24:00前). 二.分析结果 特点之一:通讯方便 <渴了么>这个安卓APP特点之一就是通讯方便 ...

  3. Ubuntu环境下No module named '_tkinter'错误的解决

    在Ubuntu环境下运行下面代码: import matplotlib as plt 出现以下错误: No module named '_tkinter' 解决方法: sudo apt-get ins ...

  4. 寒假作业2:简化电梯设计elevator

    Github仓库地址:hua-kui 寒假学习计划:学习计划 - 题目背景 一栋10层的大楼(楼层编号1-10),设有一台无限载重的电梯,初始时电梯停在1层.电梯移动1层的耗时为1,在某一层停靠的耗时 ...

  5. VC++调试基础

    一.调试基础 调试快捷键 F5:  开始调试 Shift+F5: 停止调试 F10:   调试到下一句,这里是单步跟踪 F11:   调试到下一句,跟进函数内部 Shift+F11:  从当前函数中跳 ...

  6. 配置java环境 启动服务

    1:查看当前的Java JDK版本,是否符合要求,下载的为2.4.4版本,因此满足条件 [root@7 ~]# java -version openjdk version "1.8.0_65 ...

  7. PHP中类型约束

    类型约束 什么叫类型约束? 就是要求某个变量只能使用(接收,存储)某种指定的数据类型: php属于“弱类型语言”,通常不支持类型约束: 相应的,强类型语言,类型约束却是其“基本特征”. php中,只支 ...

  8. mysql中一些表选项

    表选项列表 表选项就是,创建一个表的时候,对该表的整体设定,主要有如下几个: charset = 要使用的字符编码, engine = 要使用的存储引擎(也叫表类型), auto_increment ...

  9. 我以前不知道的 Session

    之前只知道 Session 是服务器与客户端的一个会话,有默认过期时间,是服务器端的技术,与之对应的是 Cookie 技术,是客户端技术. 下面的几点是之前不知道的:[或者是忘了] 1 . Sessi ...

  10. 【前端学习笔记】JavaScript JSON对象相关操作

    //JSON方法 //JSON.parse(); var json = '{"name":"zj","age":23}'; JSON.par ...