又是一个看了题解以后还坑了一天的题…… 结果最后发现是抄代码的时候少写了一个负号。

题意:

  有一个n*m的网格,其中每个格子上都有0~9的数字。现在你可以玩K次游戏。

  一次游戏是这样定义的: 你可以选任意之前没有走过的格子作为起点。然后走任意步,其中每一步你可以向右或者向下走任意格。假如从(x1, y1)走到(x2, y2)需要花费能量|x1-x2|+|y1-y2|-1,如果这一步和上一步格子的数字相同,那么可以获得格子上相应数字的能量。能量可以为负值。

  问你,在K次以内走完所以格子最多能得到多少能量,若走不完,输出-1 。

思路:(直接抄题解)

  最小K路径覆盖的模型,用费用流或者KM算法解决,构造二部图,X部有N*M个节点,源点向X部每个节点连一条边,流量1,费用0,Y部有N*M个节点,每个节点向汇点连一条边,流量1,费用0,如果X部的节点x可以在一步之内到达Y部的节点y,那么就连边x->y,费用为从x格子到y格子的花费能量减去得到的能量,流量1,再在X部增加一个新的节点,表示可以从任意节点出发K次,源点向其连边,费用0,流量K,这个点向Y部每个点连边,费用0,流量1,最这个图跑最小费用最大流,如果满流就是存在解,反之不存在,最小费用的相反数就是可以获得的最大能量。

代码:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <time.h> using namespace std; const int INF = <<;
const int MAXN = ; struct Edge {
int from, to, cap, flow, cost;
Edge(int from, int to, int cap, int flow, int cost)
: from(from), to(to), cap(cap), flow(flow), cost(cost) {}
}; struct MCMF {
int n, m, s, t;
vector<Edge> edges;
vector<int> G[MAXN]; int inq[MAXN];
int d[MAXN];
int p[MAXN];
int a[MAXN];
int cnt[MAXN]; void init(int n) {
this->n = n;
for (int i = ; i < n; i++) G[i].clear();
edges.clear();
} void addEdge(int from, int to, int cap, int cost) {
edges.push_back(Edge(from, to, cap, , cost));
edges.push_back(Edge(to, from, , , -cost));
m = edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} bool BellmanFord(int s, int t, int &flow, int &cost) {
for (int i = ; i < n; i++) d[i] = INF;
memset(inq, , sizeof(inq));
memset(cnt, , sizeof(cnt));
d[s] = ; inq[s] = ; p[s] = ; a[s] = INF;
bool flag = false;
queue<int> Q;
Q.push(s);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
//printf("u: %d %d\n", u, Q.size());
inq[u] = ;
for (int i = ; i < G[u].size(); i++) {
Edge &e = edges[G[u][i]];
if (e.cap>e.flow && d[e.to] > d[u]+e.cost) {
cnt[e.to] = cnt[u]+;
if (cnt[e.to]>=n) {flag = true; break; }
//printf("u: %d v: %d\n d[u]: %d d[v]: %d cost: %d\ncap: %d flow: %d\n", u, e.to, d[u], d[e.to], e.cost, e.cap, e.flow);
d[e.to] = d[u] + e.cost;
p[e.to] = G[u][i];
a[e.to] = min(a[u], e.cap-e.flow);
if (!inq[e.to]) { Q.push(e.to); inq[e.to] = ; }
}
}
if (flag)break;
}
if (d[t]==INF) return false;
flow += a[t];
cost += d[t]*a[t];
int u = t;
while (u!=s) {
edges[p[u]].flow += a[t];
edges[p[u]^].flow -= a[t];
u = edges[p[u]].from;
}
return true;
} pair<int, int> MinCost(int s, int t) {
int flow = , cost = ;
while (BellmanFord(s, t, flow, cost)) ;
return make_pair(flow, cost);
}
void print(){
for(int i=;i<n;i++){
printf("%d :",i);
for(int j=;j<G[i].size();j++)
printf("(%d %d %d)",edges[G[i][j]].to,edges[G[i][j]].cap,edges[G[i][j]].cost);
puts("");
}
}
}solver; int N, M, K;
int grid[][]; void solve() {
char tmp[];
scanf("%d%d%d", &N, &M, &K);
for (int i = ; i < N; i++) {
scanf("%s", tmp);
for (int j = ; j < M; j++) {
grid[i][j] = tmp[j] - '';
}
}
int num = N*M; //总的格点数
//格点的编号规则: grid[i][j] = i*M + j //建图:
//编号规则:
/*
0~num : 每个点的第一部分
num~2*num-1 : 每个点的第二部分
2*num: 原点
2*num+1 : 额外点
2*num+2 :
*/
int st = *num, ad = st+, ed = ad+;
solver.init(*num+);
for (int i = ; i < num; i++) { //原点到第一部分的每个点有一条容量为1,费用为0的边
solver.addEdge(st, i, , );
}
for (int i = num; i < *num; i++) { //每个点的第二部分到汇点有一个容量为1,费用为0
solver.addEdge(i, ed, , );
}
solver.addEdge(st, ad, K, );
for (int i = num; i < *num; i++) { //额外点到每个点的第二部分的边
solver.addEdge(ad, i, , );
}
for (int i = ; i < N; i++)
for (int j = ; j < M; j++) { //对于每一个点
for (int x = i+; x < N; x++) {
int cost = x-i-;
if (grid[i][j]==grid[x][j])
cost -= grid[i][j];
solver.addEdge(i*M+j, num+x*M+j, , cost);
} for (int y = j+; y < M; y++) {
int cost = y-j-;
if (grid[i][j]==grid[i][y])
cost -= grid[i][j];
solver.addEdge(i*M+j, num+i*M+y, , cost);
}
}
//puts("ok");
//solver.print(); pair<int, int> ans = solver.MinCost(st, ed);
if (ans.first==num)
printf("%d\n", -ans.second);
else
puts("-1");
} int main() {
#ifdef Phantom01
freopen("HDU4862.txt", "r", stdin);
#endif //Phantom01 int Case;
scanf("%d", &Case);
for (int i = ; i <= Case; i++) {
printf("Case %d : ", i);
solve();
} return ;
}

HDU4862

  

HDU 4862 Jump 费用流的更多相关文章

  1. HDU 4862(费用流)

    Problem Jump (HDU4862) 题目大意 给定一个n*m的矩形(n,m≤10),每个矩形中有一个0~9的数字. 一共可以进行k次游戏,每次游戏可以任意选取一个没有经过的格子为起点,并且跳 ...

  2. HDU 4862 Jump(更多的联合培训学校1)(最小费用最大流)

    职务地址:pid=4862">HDU4862 最小费用流做的还是太少. 建图想不出来. . . 直接引用官方题解的话吧... 最小K路径覆盖的模型.用费用流或者KM算法解决,构造二部图 ...

  3. Mining Station on the Sea HDU - 2448(费用流 || 最短路 && hc)

    Mining Station on the Sea Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav ...

  4. Coding Contest HDU - 5988(费用流)

    题意: 有n个区域和m条路,每个区域有a[i]个人和b[i]个食物,然后是m条路连接两个区域,这条路容量为cap,这条路断掉的概率为p,第一个经过的时候一定不会断,后面的人有概率p会断,现在需要所有人 ...

  5. HDU 4862 JUMP 最小费用最大流

    2014 多校的B题,由于我不怎么搞图论,当时碰到这个题目,我怎么想都没往网络流方面弄,不过网络流真的是个好东西,对于状态多变,无法用动规或者数据结构来很好表示的时候,非常有用 这个题目要求每个点一定 ...

  6. HDU 4862 Jump(最小K路径覆盖)

    输入一个n×m网格图,每个结点的值为0-9,可以从任意点出发不超过k次,走完每个点且仅访问每个结点一次,问最终的能量最大值.不可全部走完的情况输出-1. 初始能量为0. 而结点(x,y)可以跳跃到结点 ...

  7. hdu 4322 最大费用流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4322 #include <cstdio> #include <cstring> ...

  8. HDU 4862 Jump 任意起点最大权K链不相交覆盖

    你可以从任意起点开始起跳最多K次 每次跳你可以选择往右或者往下跳 从(x1,y1)跳到(x2,y2) 消耗的能量是曼哈顿距离-1 但是如果每次跳的起点和终点格子里的数字是相同的为X的话你会得到X能量 ...

  9. Going Home HDU - 1533 费用流

    http://acm.hdu.edu.cn/showproblem.php?pid=1533 给一个网格图,每两个点之间的匹配花费为其曼哈顿距离,问给每个的"$m$"匹配到一个&q ...

随机推荐

  1. Windows 10 秋季更新错误

    uefi 启动丢失修复 bcdboot c:\windows /s y: /f uefi /l zh-cn 0x80240034 你尝试安装的内部版本是有签名的外部测试版.若要继续安装,请启用外部测试 ...

  2. Linux与Windows信息交互快捷方法

    要把windows上的D盘挂载的Linux上,首先要知道windows的用户名和密码 假设用户名是administrator,密码是123456 首先,在linux上创建一个挂载的目标目录 mkdir ...

  3. centos下nginx配置

    转自  http://www.linuxidc.com/Linux/2016-09/134907.htm 安装所需环境 Nginx 是 C语言 开发,建议在 Linux 上运行,当然,也可以安装 Wi ...

  4. oracle11g文件系统库迁移到ASM库上面

    最近把oracle11g的文件系统库迁移到了asm库上面. 迁移过程大致如下: 最少停机方案: 实例joinpay02 | |数据库joinpay02 需要改动的文件: 数据文件 控制文件 redo文 ...

  5. shell编程, 100文钱买100只鸡, 简单实现

    今天碰到一个有趣的问题: 群友用shell写的一个: #!/bin/bash # 百元买百鸡,每种鸡至少买一只 all= # 公鸡每只多少元 read -p '公鸡多少文一只: ' gongji # ...

  6. Intellij IDEA 2018.3激活破解方法(解决key is invalid)

    1.程序安装包: https://download.jetbrains.8686c.com/idea/ideaIU-2018.3.exe 2.破解补丁:http://idea.lanyus.com/j ...

  7. (2016北京集训十)【xsy1529】小Q与进位制 - 分治FFT

    题意很简单,就是求这个数... 其实场上我想出了分治fft的正解...然而不会打...然后打了个暴力fft挂了... 没啥好讲的,这题很恶心,卡常卡精度还爆int,要各种优化,有些dalao写的很复杂 ...

  8. C语言Huffman压缩和解压

    符号表结构体: struct node { // 字符串形式存储的Huffman编码 char code[MAX_CODE_LENGTH]; // 这个字符在文件中出现的次数 long count; ...

  9. 传纸条 NOIP2008 洛谷1006 二维dp

    二维dp 扯淡 一道比较基本的入门难度的二维dp,类似于那道方格取数,不过走过一次的点下次不能再走(看提交记录里面好像走过一次的加一次a[i][j]的也AC了,,),我记得当年那道方格取数死活听不懂, ...

  10. (六)storm-kafka源代码走读之PartitionManager

    PartitionManager算是storm-kafka的核心类了,如今開始简单分析一下.还是先声明一下,metric部分这里不做分析. PartitionManager主要负责的是消息的发送.容错 ...