• HDU


    Description

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

    (n,mle 10,kle 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
    ", _Case, (flow == n * m ? -cost : -1));
    	}
    	return 0;
    }
    
  • 相关阅读:
    将jar包安装到本地repository中,---以greenplum.jar举例
    推荐系统学习起步
    代理模式详解:静态代理、JDK动态代理与Cglib动态代理
    MyBatis(四):自定义持久层框架优化
    MyBatis(二):自定义持久层框架思路分析
    MyBatis(一):JDBC使用存在的问题
    PHP编程趣事:能喝几瓶啤酒?
    Linux下的两个经典宏定义
    C/C++中常用的字符串处理函数和内存字符串函数
    设计模式之适配器模式(Adapter Pattern)C++实现
  • 原文地址:https://www.cnblogs.com/aziint/p/9495864.html
Copyright © 2020-2023  润新知