网络流大法吼

不想用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. 2019-03-29 Vagrant Docker Toolbox 下载安装

    1.无脑安装Vagrant Vagrant是一个基于Ruby的工具,用于创建和部署虚拟化开发环境.它 使用Oracle的开源VirtualBox虚拟化系统,使用 Chef创建自动化虚拟环境. http ...

  2. Servlet 3.1 标准(一)

    概述 什么是Servlet Servlet 是一个基于Java 的Web组件,由容器管理生成的动态内容.就像其他的Java组件一样,Servlet是平台无关的Java类所编译成的字节码,可以被动态加载 ...

  3. 2018年九个很受欢迎的vue前端UI框架

    最近在逛各大网站,论坛,SegmentFault等编程问答社区,发现Vue.js异常火爆,重复性的提问和内容也很多,小编自己也趁着这个大前端的热潮,着手学习了一段时间的Vue.js,目前用它正在做自己 ...

  4. maven下载的jar包可以查看源码

    1:Maven命令下载源码和javadocs 当在IDE中使用Maven时如果想要看引用的jar包中类的源码和javadoc需要通过maven命令下载这些源码,然后再进行引入,通过mvn命令能够容易的 ...

  5. Spring Boot由jar包转成war包

    Spring Boot由jar包转成war包 spring boot 默认是以jar包形式启动web程序,在新建spring boot项目时候可以选择war包的启动方式. 建议在开发的时候建立以jar ...

  6. 在IntelliJ IDEA中创建Web项目

    在IntelliJ IDEA中创建Web项目 在IntelliJ IDEA中创建Web项目1,创建Maven WebProject选择File>New>Project 出现New Proj ...

  7. Android 经常使用设计模式(一)

    由于项目变更的频繁性,作为一名程序猿,我们须要掌握设计模式的必要性.就不言而喻~~.以下就是一些我自己学习的设计模式总结. 接下来,主要是针对几个比較经常使用模式进行解说,主要是以下几种: 观察者模式 ...

  8. 一个关于 UIPickerView 的 bug

    首先,我下描写叙述一下bug的发生情况: 在使用UIPickerView实现选择城市的时候.出现这样一个Bug 1.在iOS 6的系统上 2.Picker的数据上省份一栏选择了"香港&quo ...

  9. MyEclipse改动内存大小

    方式一网上说的(没有測试过): 找到MyEclipse的安装文件夹,一般假设不改动的话默觉得C:\MyEclipse10.1\Genuitec\MyEclipse 10.1有一个myeclipse.i ...

  10. 网页爬虫框架jsoup介绍

    序言:在不知道jsoup框架前,因为项目需求.须要定时抓取其它站点上的内容.便想到用HttpClient方式获取指定站点的内容.这样的方法比較笨,就是通过url请求指定站点.依据指定站点返回文本解析. ...