网络流大法吼

不想用DP的我选择了用网络流……

建模方法:

从源点向(1,1)连一条容量为2(走两次),费用为0的边

从(n,n)向汇点连一条容量为2,费用为0的边

每个方格向右边和下边的方格连一条容量为inf,费用为0的边

走到每个方格,会取出方格上的数。每个方格的数只会被取走一次。

于是我们考虑拆点

每个方格向拆出的点连一条容量为1(只能被取走一次),费用为方格上的数的边

由于每个方格不一定只走一次,所以再连一条容量为inf,费用为0的边

然后跑最大费用最大流就行了~


我的代码中把边上的费用取相反数,跑最小费用最大流,最后得出的最小费用取负就是答案啦~!

下面是代码:

#include <bits/stdc++.h>

using namespace std;

const int maxn = 210;

struct edge {
int flow, cap, cost, t, next;
}e[maxn * 50];
int n, m, s, t, p = -1, head[maxn], maxflow, mincost = 0, pre[maxn], dis[maxn], a[maxn][maxn];
bool vis[maxn]; void add_edge(int s, int t, int cap, int cost) {
p++;
e[p].t = t;
e[p].cap = cap;
e[p].cost = cost;
e[p].next = head[s];
head[s] = p;
} bool spfa() {
queue < int > q;
while(!q.empty())q.pop();
memset(vis, 0, sizeof(vis));
vis[s] = 1;
q.push(s);
memset(dis, 0x7f, sizeof(dis));
memset(pre, -1, sizeof(pre));
dis[s] = 0;
while(!q.empty()) {
int k = q.front();
q.pop();
vis[k] = false;
for(int i = head[k]; i != -1; i = e[i].next) {
if(e[i].cap && dis[e[i].t] > dis[k] + e[i].cost) {
dis[e[i].t] = dis[k] + e[i].cost;
pre[e[i].t] = i;
if(!vis[e[i].t]) {
vis[e[i].t] = true;
q.push(e[i].t);
}
}
}
}
// for(int i = 0; i <= n * n; i++) cout << dis[i] << " ";
// cout << dis[t] << endl;
if(dis[t] == 0x7f7f7f7f) return false;
else return true;
} void MCMF() {
while(spfa()) {
int mf = 0x7fffffff;
for(int i = pre[t]; i != -1; i = pre[e[i ^ 1].t]) {
mf = min(mf, e[i].cap);
// cout << i << " " << pre[e[i ^ 1].t] << endl;
// cout << e[2].cap << endl;
}
maxflow += mf;
for(int i = pre[t]; i != -1; i = pre[e[i ^ 1].t]) {
e[i].cap -= mf;
e[i ^ 1].cap += mf;
}
mincost += mf * dis[t];
}
} int pos(int x, int y) {
return (x - 1) * n + y;
} int main() {
memset(head, -1, sizeof(head));
cin >> n;
s = 0, t = maxn - 3;
int x, y, z;
while(1) {
cin >> x >> y >> z;
if(!(x || y || z)) break;
a[x][y] = z;
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
add_edge(pos(i, j), pos(i, j) + n * n, 1, -a[i][j]);
add_edge(pos(i, j) + n * n, pos(i, j), 0, a[i][j]);
add_edge(pos(i, j), pos(i, j) + n * n, 0x7fffffff, 0);
add_edge(pos(i, j) + n * n, pos(i, j), 0, 0);
if(i < n) {
add_edge(pos(i, j) + n * n, pos(i + 1, j), 0x7fffffff, 0);
add_edge(pos(i + 1, j), pos(i, j) + n * n, 0, 0);
}
if(j < n) {
add_edge(pos(i, j) + n * n, pos(i, j + 1), 0x7fffffff, 0);
add_edge(pos(i, j + 1), pos(i, j) + n * n, 0, 0);
}
}
}
add_edge(s, pos(1, 1), 2, 0);
add_edge(pos(1, 1), s, 0, 0);
add_edge(pos(n, n) + n * n, t, 2, 0);
add_edge(t, pos(n, n) + n * n, 0, 0);
MCMF();
cout << -mincost << endl;
return 0;
}

qwq

洛谷P1004 方格取数的更多相关文章

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

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

  2. 洛谷 P1004 方格取数 题解

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

  3. 洛谷 P1004 方格取数 【多进程dp】

    题目链接:https://www.luogu.org/problemnew/show/P1004 题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 ...

  4. 洛谷 P1004 方格取数

    题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0.如下图所示(见样例): A 0 0 0 0 0 0 0 0 0 0 13 0 0 6 0 ...

  5. 【动态规划】洛谷P1004方格取数

    题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0.如下图所示(见样例): A 0 0 0 0 0 0 0 0 0 0 13 0 0 6 0 ...

  6. 洛谷P1004 方格取数-四维DP

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

  7. Codevs 1043 ==洛谷 P1004 方格取数

    题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0.如下图所示(见样例): A 0 0 0 0 0 0 0 0 0 0 13 0 0 6 0 ...

  8. 洛谷 P1004 方格取数 【多线程DP/四维DP/】

    题目描述(https://www.luogu.org/problemnew/show/1004) 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0. ...

  9. 四维动规 洛谷P1004方格取数

    分析:这个题因为数据量非常小,可以直接用四维的DP数组 dp[i][j][k][l]表示第一个人走到位置(i,j),第二个人走到位置[k][l]时所取的数的最大和 状态转移方程可以轻松得出为:dp[i ...

随机推荐

  1. VLC编译

    http://blog.csdn.net/hdh4638/article/details/7602321 1 下载代码 ki.videolan.org/VLC_Source_code git colo ...

  2. Java基础学习总结(61)——Java项目开发要注意的60个问题

    1. 首先写代码的时候最好不要有缺陷.最好的修复方法就是让 bug 胎死腹中. 良好的单元测试 强制数据库约束 使用输入验证框架 避免未实现的"else"条件 在应用到主程序之前知 ...

  3. C# 低耦合 高内聚

    低耦合 loosely Coupling 松散的耦合关系=炮友 couple=夫妻 夫妻=法律约束.家庭.生活.财产.繁衍 炮友:吃喝玩乐,不会产生感情方面的依赖       内聚性 内聚性又称块内联 ...

  4. 4种方法让SpringMVC接收多个对象

    问题背景: 我要在一个表单里同一时候一次性提交多名乘客的个人信息到SpringMVC,前端HTML和SpringMVC Controller里该怎样处理? 第1种方法:表单提交,以字段数组接收: 第2 ...

  5. Threejs 官网 - 怎样执行本地的东西(How to run things locally)

    Threejs 官网 - 怎样执行本地的东西(How to run things locally) 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循&qu ...

  6. 《coredump问题原理探究》Linux x86版7.8节vector相关的iterator对象

    在前面看过了一个vectorcoredump的样例,接触了vector的iterator,能够知道vector的iterator仅仅有一个成员_M_current指向vector某一个元素. 先看一个 ...

  7. openssl之EVP系列之2---对称加密算法概述

    openssl之EVP系列之2---对称加密算法概述     ---依据openssl doc/crypto/EVP_EncryptInit.pod和doc/ssleay.txt cipher.doc ...

  8. web后台知识点整理

    五.JEE 适用于创建server端的大型的软件服务系统 1. JEE : JAVA  PLATFORM  ENTERPRISE  DEDITON 2.是一个规范集.技术集.框架集(API集) 一种技 ...

  9. AI安全初探——利用深度学习检测DNS隐蔽通道

    AI安全初探——利用深度学习检测DNS隐蔽通道 目录 AI安全初探——利用深度学习检测DNS隐蔽通道 1.DNS 隐蔽通道简介 2. 算法前的准备工作——数据采集 3. 利用深度学习进行DNS隐蔽通道 ...

  10. Oracle RMAN备份中catalog和nocatalog区别

    nocatalog方式:用control file作为catalog,每一次备份都要往控制文件里面写好多备份信息,控制文件里面会有越来越多的备份信息,即RMAN的备份信息写在本地控制文件里面. cat ...