码迷,mamicode.com
首页 > 其他好文 > 详细

HDU - 4862 Jump

时间:2018-08-18 00:40:46      阅读:114      评论:0      收藏:0      [点我收藏+]

标签:class   eof   case   amp   names   ase   dig   flow   printf   

Description

一个 \(n\times m\) 的棋盘,每个格子里有一个 \(0-9\) 的数字。每次游戏可以选取一个没有经过的格子为起点跳任意多步,可以向右或向下跳到一个没有经过的点。每次跳需要消耗两点间的曼哈顿距离减一的能量,若每次跳的起点和终点的数字相同,可以获得该数字的能量。问 \(k\) 次或更少次游戏后,是否能访问整张图,若能输出最大能量。

\(n,m\le 10,k\le 100\)

Solution

完蛋了网络流水平大退化

费用流。

拆点,每个格子拆成 \(x,y\) ,连边 \((S,x,1,0)\)\((y,T,1,0)\) ,如果格子 \(i\) 能一跳到达 \(j\) 则连边 \((x_i,y_j,1,消耗-所得)\)

新建节点 \(Q\) ,连边 \((Q,y,1,0)\)

为什么要这样建边呢?

咕咕咕

#include<bits/stdc++.h>
using namespace std;

template <class T> void read(T &x) {
    x = 0; bool flag = 0; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) flag |= (ch == '-');
    for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48; flag ? (x = -x) : 0;
}

#define N 500
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define INF 0x3f3f3f3f

struct edge { int u, v, c, w, next; }e[100001];
int S, T, flow, cost, head[N], tot = 1, dis[N], pre[N];
queue<int> q;
bool inq[N];
inline void insert(int u, int v, int c, int w) { e[++tot].u = u, e[tot].v = v, e[tot].c = c, e[tot].w = w, e[tot].next = head[u], head[u] = tot; }
inline void add(int u, int v, int c, int w) { insert(u, v, c, w), insert(v, u, 0, -w); }
inline bool spfa() {
    rep(i, S, T) dis[i] = INF; dis[S] = 0; q.push(S);
    while (!q.empty()) {
        int u = q.front(); q.pop(); inq[u] = 0;
        for (int i = head[u], v, w; i; i = e[i].next) if (e[i].c > 0 && dis[v = e[i].v] > dis[u] + (w = e[i].w)) {
            dis[v] = dis[u] + w, pre[v] = i;
            if (!inq[v]) q.push(v); inq[v] = 1;
        }
    }
    return dis[T] != INF;
}
inline void mcf() {
    int d = INF;
    for (int i = T; (i ^ S); i = e[pre[i]].u) d = min(d, e[pre[i]].c);
    flow += d;
    for (int i = T; (i ^ S); i = e[pre[i]].u) e[pre[i]].c -= d, e[pre[i] ^ 1].c += d, cost += d * e[pre[i]].w;
}

int a[N][N], n, m, K;
char s[N];
inline int x(int i, int j) { return (i - 1) * m + j; }
inline int y(int i, int j) { return x(i, j) + n * m; }

int main() {
    int Case; read(Case);
    rep(_Case, 1, Case) {
        memset(head, 0, sizeof head), tot = 1;
        read(n), read(m), read(K);
        int Q = n * m * 2 + 1; S = 0, T = Q + 1;
        rep(i, 1, n) {
            scanf("%s", s + 1);
            rep(j, 1, m) a[i][j] = s[j] - '0';
        }
        add(S, Q, K, 0);
        rep(i, 1, n) rep(j, 1, m) {
            add(S, x(i, j), 1, 0), add(y(i, j), T, 1, 0);
            add(Q, y(i, j), 1, 0);
            rep(k, j + 1, m) add(x(i, j), y(i, k), 1, k - j - 1 - (a[i][j] == a[i][k] ? a[i][j] : 0));
            rep(k, i + 1, n) add(x(i, j), y(k, j), 1, k - i - 1 - (a[i][j] == a[k][j] ? a[i][j] : 0));
        }
        flow = 0, cost = 0;
        while (spfa()) mcf();
        printf("Case %d : %d\n", _Case, (flow == n * m ? -cost : -1));
    }
    return 0;
}

HDU - 4862 Jump

标签:class   eof   case   amp   names   ase   dig   flow   printf   

原文地址:https://www.cnblogs.com/aziint/p/9495864.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!