【HDU】4862 Jump 费用流

2024-09-05 15:32
文章标签 费用 hdu jump 4862

本文主要是介绍【HDU】4862 Jump 费用流,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

传送门:【HDU】4862 Jump



题目大意:给你一个N行M列个格子的矩阵,矩阵每个格子中有一个值(0~9),一开始你有活力值为0,然后你可以进行最多K次游戏,每次可以任选矩阵中的一个点作为顶点,然后开始游戏,每次你可以选择从这个点跳到它的右边的点或者下边的点或者不动。每次跳跃,你将支付两个点的曼哈顿距离-1的活力值,能量值可以为负。如果一次跳跃的起点和终点的格子中的值相同,你的活力值可以增加这个值大小的值。每个格子最多只可以经过一次。每次游戏你可以跳任意多次,但不能违反规则。

现在你的任务是要在必须将所有的格子都跳过后能得到的最多的活力值。当然不必满足将K次机会全部用掉。



题目分析:

这次女队写出来的题目我没写出来,是该好好反思了,唉。。。

都怪平时不努力Q w Q

简单说一下这题吧,说实话其实也不难,可是当时却没去想。。

首先题目要求每个格子必须遍历一次,最多也只能遍历一次,那么可以把一个点拆成两个点i、i',建边(i,i',1,-x)中间的权值设为比所有点的权值和还大就行了(当然求的是最大费用流,权值取反,最大的意思就是最小),这样就能保证如果可以经过这个点,那么就会优先经过这个点。然后设立父子源点以及父子汇点,其中父源点向子源点输送K的流量(fas,sons,K,0),子源点向每个格子输送1的流量(sons,i,1,0),这样就能保证最多进行K次游戏了~。同理汇点一个方法处理一下。

然后每个格子向他能跳到的点建边(i’,j,1,-(-(曼哈顿距离-1)+a)),其中的a当两个格子相同时等于相同的那个值,否则等于0。

最后跑一次费用流即可,设得到的费用为cost,如果(-cost)/x != n*m,那么说明无解。

否则输出(-cost)%x。

最后提醒一下我错的地方:并不是一定要求得最小费用最大流的,因为可能只要小于K次游戏就能得到最优解的,但是如果要求最大流的话,那么可能会错失最优解,反而错误,所以最好的方法是要么cost不能再减小的时候就退出(为什么这样可行呢?因为每次都是最短路,所以每次得到的最短路大小都是递增的,所以一次不满足,之后的一定也不满足了)。当然还有别的方法可以避免这个问题了,我就不熬述了。


唉,果然还是太弱,努力努力再努力!!!!!!!!!!!!!!!!!


代码如下:


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REPV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define clear( a , x ) memset ( a , x , sizeof a )
#define copy( a , x ) memcpy ( a , x , sizeof a )const int MAXN = 250 ;
const int MAXQ = 1000000 ;
const int MAXE = 1000000 ;
const int INF = 0x3f3f3f3f ;struct Edge {int v , c , w , n ;Edge () {}Edge ( int var , int cost , int val , int next ) :v ( var ) , c ( cost ) , w ( val ) , n ( next ) {}
} ;struct NetWork {Edge E[MAXE] ;int H[MAXN] , cntE ;int d[MAXN] , cur[MAXN] , a[MAXN] ;int Q[MAXQ] , head , tail , inq[MAXN] ;int s , t ;int S , T ;int cost , flow ;int n , m , K ;int G[MAXN][MAXN] ;void init () {cntE = 0 ;clear ( H , -1 ) ;}void addedge ( int u , int v , int c , int w ) {E[cntE] = Edge ( v , c ,  w , H[u] ) ;H[u] = cntE ++ ;E[cntE] = Edge ( u , 0 , -w , H[v] ) ;H[v] = cntE ++ ;}int spfa () {clear ( inq , 0 ) ;clear ( d , INF ) ;d[s] = 0 ;a[s] = INF ;cur[s] = -1 ;head = tail = 0 ;Q[tail ++] = s ;while ( head != tail ) {int u = Q[head ++] ;if ( head == MAXQ )head = 0 ;inq[u] = 0 ;for ( int i = H[u] ; ~i ; i = E[i].n ) {int v = E[i].v ;if ( E[i].c && d[v] > d[u] + E[i].w ) {d[v] = d[u] + E[i].w ;a[v] = min ( a[u] , E[i].c ) ;cur[v] = i ;if ( !inq[v] ) {inq[v] = 1 ;if ( d[v] < d[head] ) {Q[-- head] = v ;if ( head == 0 )head = MAXQ - 1 ;}else {Q[tail ++] = v ;if ( tail == MAXQ )tail = 0 ;}}}}}if ( d[t] == INF )return 0 ;if ( cost + d[t] * a[t] < cost )cost += d[t] * a[t] ;elsereturn 0 ;flow += a[t];for ( int i = cur[t] ; ~i ; i = cur[E[i ^ 1].v] ) {E[i].c -= a[t] ;E[i ^ 1].c += a[t] ;}return 1 ;}int MCMF () {cost = flow = 0 ;while ( spfa () ) ;return -cost ;}void input () {scanf ( "%d%d%d" , &n , &m , &K ) ;int nm = n * m ;S = 2 * nm , T = S + 1 ;s = T + 1 , t = s + 1 ;addedge ( s , S , K , 0 ) ;addedge ( T , t , K , 0 ) ;REP ( i , n ) {REP ( j , m ) {scanf ( "%1d" , &G[i][j] ) ;addedge ( S , i * m + j , 1 , 0 ) ;addedge ( i * m + j , nm + i * m + j , 1 , -100000 ) ;addedge ( nm + i * m + j , T , 1 , 0 ) ;}}REP ( i , n )REP ( j , m )REPF ( k , 1 , 10 ) {if ( j + k < m )addedge ( nm + i * m + j , i * m + j + k , 1 , k - 1 - ( G[i][j] == G[i][j + k] ? G[i][j] : 0 ) ) ;if ( i + k < n )addedge ( nm + i * m + j , ( i + k ) * m + j , 1 , k - 1 - ( G[i][j] == G[i + k][j] ? G[i][j] : 0 ) ) ;}}void solve () {init () ;input () ;int ans = MCMF () ;if ( ans / 100000 != n * m )printf ( "-1\n" ) ;elseprintf ( "%d\n" , ans % 100000 ) ;}
} ;NetWork nw ;int main () {int T , cas ;for ( scanf ( "%d" , &T ) , cas = 1 ; cas <= T ; ++ cas ) {printf ( "Case %d : " , cas ) ;nw.solve () ;}return 0 ;
}


这篇关于【HDU】4862 Jump 费用流的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1139351

相关文章

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

hdu 3790 (单源最短路dijkstra)

题意: 每条边都有长度d 和花费p,给你起点s 终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 解析: 考察对dijkstra的理解。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstrin

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

hdu 1102 uva 10397(最小生成树prim)

hdu 1102: 题意: 给一个邻接矩阵,给一些村庄间已经修的路,问最小生成树。 解析: 把已经修的路的权值改为0,套个prim()。 注意prim 最外层循坏为n-1。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstri

hdu 1285(拓扑排序)

题意: 给各个队间的胜负关系,让排名次,名词相同按从小到大排。 解析: 拓扑排序是应用于有向无回路图(Direct Acyclic Graph,简称DAG)上的一种排序方式,对一个有向无回路图进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u 在v 的前面。该序列说明了顶点表示的事件或状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时