HDU4862-Jump(最大流量最大费用流)

题意:有n*m的格子,每一个格子包含一个数字,0-9。你初始的能量为0,你可以玩k次,每一个你可以选择你现在的格子的正下方或者正右方的任意一个格子跳,但必须是之前没有跳过的格子。每玩一次你都可以跳任意次。每跳一次,从(x1, y1) 到 (x2, y2),你将花费|x1-x2|+|y1-y2|-1的能量,如果起止格子的数字相同,你能获得格子里数字的能量。

问你在把每一个格子都经过的基础上,所能得到的最大能量。

每个格子只能经过一个,你可以跳少于k次。你的能量可以为负数。

>>之前做过成环覆盖所有点的题,拆点建立二分图,此题和那个题感觉有点像。

建图的方法就是源点连所有X部,流量为1,权值为0,所有Y部连汇点,流量是1,权值为0。

能够从a点走到b点,就从a的X部到b的Y部,权值就是花费。

然后在X部添加一个点Q,从源点连到Q流量为k,权值为0的边,Q到Y部每一个点都连流量为1,权值为0的边,来保证玩k次。

最后求一个最大流量最大费用就好了。

>>建图很巧妙,但是。。。不是很懂。。。。先记下方法了。。。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <bitset>
#include <cstdio>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <map>
#include <set>
#define pk(x) printf("%d\n", x)
using namespace std;
#define PI acos(-1.0)
#define EPS 1E-6
#define clr(x,c) memset(x,c,sizeof(x))
//#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;
const int MAXV = 410;
const int INF = 1<<30;

struct Edge { int to, cap, cost, rev; };
vector<Edge> G[MAXV];
int dist[MAXV], prv[MAXV], pre[MAXV], in[MAXV];
queue<int> que;

void addedge(int from, int to, int cap, int cost) {
    G[from].push_back((Edge){to, cap, cost, G[to].size()});
    G[to].push_back((Edge){from, 0, -cost, G[from].size()-1});
}

int min_cost_max_flow(int s, int t, int f) {
    int res = 0;
    while (f > 0) {
        for (int i = 0; i <= t; ++i) dist[i] = -INF, in[i] = 0;
        dist[s] = 0;
        while (!que.empty()) que.pop();
        in[s] = 1;
        que.push(s);

        while (!que.empty()) {
            int u = que.front(); que.pop(); in[u] = 0;
            for (int i = 0; i < G[u].size(); ++i) {
                Edge &e = G[u][i];
                if (e.cap > 0 && dist[e.to] < dist[u] + e.cost) {
                    dist[e.to] = dist[u] + e.cost;
                    prv[e.to] = u;
                    pre[e.to] = i;
                    if (in[e.to] == 0) {
                        in[e.to] = 1;
                        que.push(e.to);
                    }
                }
            }
        }

        if (dist[t] == -INF) return -1;

        int d = f;
        for (int v = t; v != s; v = prv[v]) {
            d = min(d, G[prv[v]][pre[v]].cap);
        }
        f -= d;
        res += d * dist[t];
        for (int v = t; v != s; v = prv[v]) {
            Edge &e = G[prv[v]][pre[v]];
            e.cap -= d;
            G[v][e.rev].cap += d;
        }
    }
    return res;
}

int n, m, k;
char str[15][15];
int id1(int x, int y) {
    return x*m+y+1;
}
int id2(int x, int y) {
    return n*m+x*m+y+1;
}
// |x1-x2|+|y1-y2|-1
int cost(int x1, int y1, int x2, int y2) {
    int ans = -(abs(x1-x2)+abs(y1-y2)-1);
    if (str[x1][y1] == str[x2][y2]) ans += str[x1][y1] - ‘0‘;
    return ans;
}

int main()
{
    int T, cas = 0;
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d%d", &n, &m, &k);

        for (int i = 0; i < n; ++i) {
            scanf("%s", str[i]);
        }

        int src = 0;
        int q = n*m*2+1;
        int sink = n*m*2+2;

        for (int i = src; i <= sink; ++i) G[i].clear();

        addedge(src, q, k, 0);

        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {

                addedge(src, id1(i, j), 1, 0);
                addedge(id2(i,j), sink, 1, 0);
                addedge(q, id2(i,j), 1, 0);

                for (int k = i+1; k < n; ++k) {
                    addedge(id1(i, j), id2(k, j), 1, cost(i,j,k,j));
                }

                for (int k = j+1; k < m; ++k) {
                    addedge(id1(i,j), id2(i,k), 1, cost(i,j,i,k));
                }

            }
        }

        printf("Case %d : %d\n", ++cas, min_cost_max_flow(src, sink, n*m));
    }
    return 0;
}
时间: 2024-11-05 17:28:10

HDU4862-Jump(最大流量最大费用流)的相关文章

hdu 4862 Jump 上下界费用流

对于每个点拆点成为两个点a,b,连接a到b的上界为1,下界为1的边,保证用过一次且仅一次. 然后若点u可到达点v,则连接即可.建成了一个上下界网络,将下界拆出去,求最大费用最大流就好. #include <stdio.h> #include <iostream> #include <string.h> using namespace std; const int N=800; const int MAXE=200000; const int inf=1<<3

HDU 4862 Jump 费用流

又是一个看了题解以后还坑了一天的题…… 结果最后发现是抄代码的时候少写了一个负号. 题意: 有一个n*m的网格,其中每个格子上都有0~9的数字.现在你可以玩K次游戏. 一次游戏是这样定义的: 你可以选任意之前没有走过的格子作为起点.然后走任意步,其中每一步你可以向右或者向下走任意格.假如从(x1, y1)走到(x2, y2)需要花费能量|x1-x2|+|y1-y2|-1,如果这一步和上一步格子的数字相同,那么可以获得格子上相应数字的能量.能量可以为负值. 问你,在K次以内走完所以格子最多能得到多

HDU 4862 Jump 最小k路径覆盖 费用流

gg... 题意: 给定n*m的矩阵 选<=k个起点 每个起点可以向右或向下跳任意步 花费是2点间的曼哈顿距离 若2个格子的数字一样 则赚取格子上的数字的价值 问:遍历整个图的最小花费 若不能遍历则输出-1 #include <stdio.h> #include <string.h> #include <iostream> #include <math.h> #include <queue> #include <set> #in

hdu4862 2014多校B题/ 费用流(最优情况下用不大于K条路径覆盖)(不同的解法)

题意: 一个数字矩阵,可以出发K次,每次可以从右边或者下面走,要求(在收益最大情况下)覆盖全图,不能则输出-1.(规则:每次跳一步的时候若格子数字相等则获得该数字的能量,每跳一步消耗距离的能量).每个格子走且仅能走一次. 选<=K条路径,最优情况来覆盖全图. 显然用拆点为二分图. 一种解法:边(流量,费用) 源点向X部连边(1,0)Y部向汇点连边(1,0)X到Y,若能到,则有边(1,消耗-获得).关键点(解决每个点都覆盖,恰好起到填补的作用):在X部最上面添加一个点,源点连之(k,0)它向所有Y

BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]

3130: [Sdoi2013]费用流 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 960  Solved: 505[Submit][Status][Discuss] Description Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识.    最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量.一个合法的网络流方案必须满足:(1)每条边的实际流量都不超

BZOJ 3130: [Sdoi2013]费用流 网络流+二分

3130: [Sdoi2013]费用流 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1230  Solved: 598[Submit][Status][Discuss] Description Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识.     最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量.一个合法的网络流方案必须满足:(1)每条边的实际流量都

Lunch Time(费用流变型题,以时间为费用)

Lunch Time http://acm.hdu.edu.cn/showproblem.php?pid=4807 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 782    Accepted Submission(s): 183 Problem Description The campus of Nanjing University

【网络流24题】No.19 负载平衡问题 (费用流)

[题意] G 公司有 n 个沿铁路运输线环形排列的仓库, 每个仓库存储的货物数量不等. 如何用最少搬运量可以使 n 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入文件示例input.txt517 9 14 16 4 输出文件示例output.txt11 [分析] 其实我觉得这题可以贪心啊..n^2贪心??.没细想.. 打的是费用流.. 大概这样建图: 懒得写了..凌乱之美.. 求满流费用.. 1 #include<cstdio> 2 #include<cstdlib&

POJ 3422 kaka&#39;s matrix trvals(费用流)

#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include <map> #include <cma