HDU - 4862 Jump

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;
}
posted @ 2018-08-17 23:17  aziint  阅读(99)  评论(0编辑  收藏  举报
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.