hdu 2686 Matrix && hdu 3367 Matrix Again (最大费用最大流)

Matrix


Time Limit: 2000/1000 MS
(Java/Others)    Memory Limit: 32768/32768 K
(Java/Others)
Total Submission(s): 1394    Accepted
Submission(s): 758

Problem Description

Yifenfei very like play a number game in the n*n
Matrix. A positive integer number is put in each area of the Matrix.
Every
time yifenfei should to do is that choose a detour which frome the top left
point to the bottom right point and than back to the top left point with the
maximal values of sum integers that area of Matrix yifenfei choose. But from the
top to the bottom can only choose right and down, from the bottom to the top can
only choose left and up. And yifenfei can not pass the same area of the Matrix
except the start and end.

Input

The input contains multiple test cases.
Each case
first line given the integer n (2<n<30) 
Than n lines,each line
include n positive integers.(<100)

Output

For each test case output the maximal values yifenfei
can get.

Sample Input

2

10 3

5 10

3

10 3 3

2 5 3

6 7 10

5

1 2 3 4 5

2 3 4 5 6

3 4 5 6 7

4 5 6 7 8

5 6 7 8 9

Sample Output

28

46

80

Author

yifenfei

Source

ZJFC
2009-3 Programming Contest

Recommend

yifenfei   |   We have
carefully selected several similar problems for you:  3376 1533 3416 3081 2448

最大费用最大流,搞了好久= =!

题意:

给出一个n*n的矩阵,求(1,1)到(n,n)的两条不想交不重叠的路径,使经过的点的和最大。

开始想到的是DP,后来发现了可以用多线程DP实现:

参考:http://www.cnblogs.com/jackge/archive/2013/04/17/3025628.html

让两个进程同时进行,枚举步数K,当x1==x2||y1==y2时跳过,得状态转移方程:

dp(k, x1, y1, x2, y2) = max(dp(k-1, x1-1, y1, x2-1, y2), dp(k-1, x1-1,
y1, x2, y2-1), dp(k-1, x1, y1-1, x2-1, y2), dp(k-1, x1, y1-1,x2,
y2-1))

+ data(x1, y1) + data(x2, y2) ;

由于只能走右或下,所以坐标满足x+y=k。这样就能降低维数为3维,方程:

dp(k, x1, x2) = max(dp(k-1, x1, x2), dp(k-1, x1-1, x2), dp(k-1, x1, x2-1),
dp(k-1, x1-1, x2-1)) + data(x1, k-x1) + data(x2, k-x2) ;

code:

 1 //31MS    1196K    880 B    G++
2 #include<stdio.h>
3 #include<string.h>
4 #define N 50
5 int p[N][N];
6 int dp[2*N][N][N];
7 int max(int a,int b)
8 {
9 return a>b?a:b;
10 }
11 int Max(int a,int b,int c,int d)
12 {
13 return max(a,max(b,max(c,d)));
14 }
15 int main(void)
16 {
17 int n;
18 while(scanf("%d",&n)!=EOF)
19 {
20 memset(dp,0,sizeof(dp));
21 for(int i=0;i<n;i++)
22 for(int j=0;j<n;j++)
23 scanf("%d",&p[i][j]);
24 for(int k=1;k<2*n-2;k++)
25 for(int i=0;i<n;i++)
26 for(int j=0;j<n;j++){
27 if(i==j) continue;
28 dp[k][i][j]=Max(dp[k-1][i][j],dp[k-1][i-1][j],dp[k-1][i][j-1],dp[k-1][i-1][j-1]);
29 dp[k][i][j]+=p[i][k-i]+p[j][k-j];
30 }
31 int ans=max(dp[2*n-3][n-1][n-2],dp[2*n-3][n-2][n-1])+p[0][0]+p[n-1][n-1];
32 printf("%d\n",ans);
33 }
34 return 0;
35 }

View
Code

先拆点构图,每个点一分为二,保证了只经过一次,其实网络流的方法就已经解决了这个问题,其次构图时注意把数变为负数,求最小费用最大流。

其实构好图后就是直接套模板了,所以构图的时候注意点,处理一下(1,1)和(n,n)两个点,因为会经过两次。

code:


  1 //31MS    384K    2396 B    G++
2 #include<stdio.h>
3 #include<string.h>
4 #include<queue>
5 #define N 2005
6 #define inf 0x7ffffff
7 using namespace std;
8 struct node{
9 int u,v,c,w;
10 int next;
11 }edge[10*N];
12 int vis[N];
13 int Head[N],d[N],edgenum;
14 int pre[N],path[N];
15 void addedge(int u,int v,int c,int w)
16 {
17 edge[edgenum].u=u;
18 edge[edgenum].v=v;
19 edge[edgenum].c=c;
20 edge[edgenum].w=w;
21 edge[edgenum].next=Head[u];
22 Head[u]=edgenum++;
23
24 edge[edgenum].u=v;
25 edge[edgenum].v=u;
26 edge[edgenum].c=0;
27 edge[edgenum].w=-w;
28 edge[edgenum].next=Head[v];
29 Head[v]=edgenum++;
30 }
31 int SPFA(int s,int e)
32 {
33 memset(vis,0,sizeof(vis));
34 memset(pre,-1,sizeof(pre));
35 for(int i=0;i<=e;i++)
36 d[i]=inf;
37 queue<int>Q;
38 d[s]=0;
39 vis[s]=1;
40 Q.push(s);
41 while(!Q.empty()){
42 int u=Q.front();
43 Q.pop();
44 vis[u]=0; //这里WA了好多次
45 for(int i=Head[u];i!=-1;i=edge[i].next){
46 int v=edge[i].v;
47 int w=edge[i].w;
48 if(edge[i].c>0 && d[v]>d[u]+w){
49 pre[v]=u;
50 path[v]=i;
51 d[v]=d[u]+w;
52 if(!vis[v]){
53 vis[v]=1;
54 Q.push(v);
55 }
56 }
57 }
58 }
59 if(pre[e]!=-1) return 1;
60 return 0;
61 }
62 int cost_min_flow(int s,int e)
63 {
64 int cost=0;
65 while(SPFA(s,e)){
66 int minc=inf;
67 for(int i=e;i!=s;i=pre[i]){
68 minc=minc<edge[path[i]].c?minc:edge[path[i]].c;
69 }
70 for(int i=e;i!=s;i=pre[i]){
71 edge[path[i]].c-=minc;
72 edge[path[i]^1].c+=minc;
73 cost+=minc*edge[path[i]].w;
74 }
75 }
76 return cost;
77 }
78 int main(void)
79 {
80 int n;
81 int p[50][50];
82 while(scanf("%d",&n)!=EOF)
83 {
84 edgenum=0;
85 memset(Head,-1,sizeof(Head));
86 int k=n*n;
87 int s=0,e=2*k+1;
88 for(int i=1;i<=n;i++)
89 for(int j=1;j<=n;j++){
90 scanf("%d",&p[i][j]);
91 addedge(j+(i-1)*n,k+j+(i-1)*n,1,-p[i][j]);
92 if(j!=n) addedge(k+j+(i-1)*n,j+1+(i-1)*n,1,0);
93 if(i!=n) addedge(k+j+(i-1)*n,j+i*n,1,0);
94 }
95 addedge(s,1,2,0);
96 addedge(1,k+1,1,0);
97 addedge(2*k,e,2,0);
98 addedge(k,2*k,1,0);
99 printf("%d\n",-cost_min_flow(s,e));
100 }
101 return 0;
102 }

hdu 2686 Matrix && hdu 3367 Matrix Again
(最大费用最大流)

时间: 2024-08-08 09:37:21

hdu 2686 Matrix && hdu 3367 Matrix Again (最大费用最大流)的相关文章

HDU 6118 度度熊的交易计划 最大费用可行流

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6118 题意:中文题 分析: 最小费用最大流,首先建立源点 s ,与超级汇点 t .因为生产一个商品需要花费 a[i] 元,且上限为 b[i] ,所以我们从 s 向这些点之间连一条容量为 b[i] ,费用为 a[i] 的边.同样的道理,出售一个商品可以赚到 c[i] 元,最多出售 d[i] 个,于是我们从这些点向 t 连一条容量为 d[i] ,费用为 -c[i] 的边.最后所有的公路也是花费,从 u

HDU 3395 Special Fish(拆点+最大费用最大流)

Special Fish Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2367    Accepted Submission(s): 878 Problem Description There is a kind of special fish in the East Lake where is closed to campus o

River Problem (hdu 3947 流量等式建图 难题 最小费用最大流)

River Problem Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 515    Accepted Submission(s): 209 Problem Description The River of Bitland is now heavily polluted. To solve this problem, the Kin

HDU 3435 A new Graph Game(最小费用最大流)&amp;amp;HDU 3488

A new Graph Game Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1849    Accepted Submission(s): 802 Problem Description An undirected graph is a graph in which the nodes are connected by undir

HDU 3435 A new Graph Game(最小费用最大流)&amp;HDU 3488

A new Graph Game Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1849    Accepted Submission(s): 802 Problem Description An undirected graph is a graph in which the nodes are connected by undir

POJ 2135 Farm Tour &amp;&amp; HDU 2686 Matrix &amp;&amp; HDU 3376 Matrix Again 费用流求来回最短路

累了就要写题解,最近总是被虐到没脾气. 来回最短路问题貌似也可以用DP来搞,不过拿费用流还是很方便的. 可以转化成求满流为2 的最小花费.一般做法为拆点,对于 i 拆为2*i 和 2*i+1,然后连一条流量为1(花费根据题意来定) 的边来控制每个点只能通过一次. 额外添加source和sink来控制满流为2. 代码都雷同,以HDU3376为例. #include <algorithm> #include <iostream> #include <cstring> #in

HDU 2686 Matrix(最大费用最大流+拆点)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686 和POJ3422一样 删掉K把汇点与源点的容量改为2(因为有两个方向的选择)即可 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> const int ma

HDU 2686 Matrix 3376 Matrix Again(费用流)

HDU 2686 Matrix 题目链接 3376 Matrix Again 题目链接 题意:这两题是一样的,只是数据范围不一样,都是一个矩阵,从左上角走到右下角在从右下角走到左上角能得到最大价值 思路:拆点,建图,然后跑费用流即可,不过HDU3376这题,极限情况是300W条边,然后卡时间过了2333 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> #i

hdu 2686 Matrix 最小费用最大流

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686 Yifenfei very like play a number game in the n*n Matrix. A positive integer number is put in each area of the Matrix.Every time yifenfei should to do is that choose a detour which frome the top left