hdu 2686 Matrix最小費用の最大フロー
17999 ワード
テーマリンク:http://acm.hdu.edu.cn/showproblem.php?pid=2686
Yifei very like Play a number game in the n*n Matrix.A positive integer number is put in each are a of the Matrix.
Every time yfreenfe i shound to is that chose a detour which from the top left point to the bottom Right point and than back to the top left point with the maximal values of sum integers and the the of Matrichoft thefrom the bottom to the top can only chose left and up.And yfreenfei can not pass the same ara of the Matrix except the start and end.
n*nの行列は、各数が正の整数であり、一番左上の位置から一番右下の位置まで歩くことが要求されています。毎回右または下の方に一マスしか歩けません。そして一番右下の位置から一番左上の位置に戻ります。毎回上または左に一マスだけ行くことができます。そして、この二つのパスの数を積算します。注意各格子は一回しか歩かない(一番左上と一番右下を除く)、つまりマトリクスの個数は一回だけ加算されます。
アルゴリズムの分析:この問題はDPを使ってもいいですが、DPは考え方が限られていますので、まだよく分かりません。
一番左上を源点とし、一番右下を為替点とする。上から下へ一度行って、下から上へ行くと、上から下へ二回行くのと同じです。つまり、ソースから送金ポイントまでの価値が一番大きくて、交わらない道を見つけます。
まず、(i-1)*n+j->(i-1)*n+j+n*n(wは1(注:ソースポイントとシンクポイントは2で、2つの道を見つけたいので)を外して、コストtはマトリックス中のこの値です。
(i-1)*n+j+n->(i-1)*n+j+1(wは1、cotは0)
(i-1)*n+j+n->i*n+j(wは1、cotは0)
そして費用の流れで解決すればいいです。(問題の中で明確に説明していますが、すべての数が正しいですか?私はdis[]関数が0 WAを初期化しました。これはなぜですか?)
Yifei very like Play a number game in the n*n Matrix.A positive integer number is put in each are a of the Matrix.
Every time yfreenfe i shound to is that chose a detour which from the top left point to the bottom Right point and than back to the top left point with the maximal values of sum integers and the the of Matrichoft thefrom the bottom to the top can only chose left and up.And yfreenfei can not pass the same ara of the Matrix except the start and end.
n*nの行列は、各数が正の整数であり、一番左上の位置から一番右下の位置まで歩くことが要求されています。毎回右または下の方に一マスしか歩けません。そして一番右下の位置から一番左上の位置に戻ります。毎回上または左に一マスだけ行くことができます。そして、この二つのパスの数を積算します。注意各格子は一回しか歩かない(一番左上と一番右下を除く)、つまりマトリクスの個数は一回だけ加算されます。
アルゴリズムの分析:この問題はDPを使ってもいいですが、DPは考え方が限られていますので、まだよく分かりません。
一番左上を源点とし、一番右下を為替点とする。上から下へ一度行って、下から上へ行くと、上から下へ二回行くのと同じです。つまり、ソースから送金ポイントまでの価値が一番大きくて、交わらない道を見つけます。
まず、(i-1)*n+j->(i-1)*n+j+n*n(wは1(注:ソースポイントとシンクポイントは2で、2つの道を見つけたいので)を外して、コストtはマトリックス中のこの値です。
(i-1)*n+j+n->(i-1)*n+j+1(wは1、cotは0)
(i-1)*n+j+n->i*n+j(wは1、cotは0)
そして費用の流れで解決すればいいです。(問題の中で明確に説明していますが、すべての数が正しいですか?私はdis[]関数が0 WAを初期化しました。これはなぜですか?)
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cstdlib>
5 #include<cmath>
6 #include<algorithm>
7 #include<vector>
8 #include<queue>
9 #define inf 0x7fffffff
10 using namespace std;
11 const int maxn=20000+10;
12 const int M = 9999999;
13
14 int n,from,to;
15 struct node
16 {
17 int v,flow,cost;
18 int next;
19 }edge[M*3];
20 int head[maxn],edgenum;
21 int dis[maxn],pre[maxn],pid[maxn],vis[maxn];
22 int an[33][33];
23
24 void add(int u,int v,int flow,int cost)
25 {
26 edge[edgenum].v=v ;edge[edgenum].flow=flow;
27 edge[edgenum].cost=cost ;edge[edgenum].next=head[u];
28 head[u]=edgenum++;
29
30 edge[edgenum].v=u ;edge[edgenum].flow=0;
31 edge[edgenum].cost=-cost ;edge[edgenum].next=head[v];
32 head[v]=edgenum++;
33 }
34
35 int spfa()
36 {
37 memset(vis,0,sizeof(vis));
38 memset(dis,-1,sizeof(dis));
39 queue<int> Q;
40 Q.push(from);
41 dis[from]=0;
42 vis[from]=1;
43 while (!Q.empty())
44 {
45 int u=Q.front() ;Q.pop();
46 vis[u]=0;
47 for (int i=head[u] ;i!=-1 ;i=edge[i].next)
48 {
49 int v=edge[i].v;
50 if (edge[i].flow>0 && dis[v]<dis[u]+edge[i].cost)
51 {
52 dis[v]=dis[u]+edge[i].cost;
53 pre[v]=u;
54 pid[v]=i;
55 if (!vis[v])
56 {
57 vis[v]=1;
58 Q.push(v);
59 }
60 }
61 }
62 }
63 return dis[to];
64 }
65
66 int mincost()
67 {
68 int aug=0,maxflow=0;
69 int ans=0;
70 int ncase=0;
71 while (1)
72 {
73 aug=inf;
74 int tmp=spfa();
75 if (tmp==0) break;
76 for (int i=to ;i!=from ;i=pre[i])
77 {
78 if (edge[pid[i] ].flow<aug)
79 aug=edge[pid[i] ].flow;
80 }
81 for (int i=to ;i!=from ;i=pre[i])
82 {
83 edge[pid[i] ].flow -= aug;
84 edge[pid[i]^1 ].flow += aug;
85 }
86 ans += tmp;
87 ncase++;
88 if (ncase==2) break;
89 }
90 return ans-an[1][1]-an[n][n];
91 }
92
93 int main()
94 {
95 while (scanf("%d",&n)!=EOF)
96 {
97 memset(head,-1,sizeof(head));
98 edgenum=0;
99 for (int i=1 ;i<=n ;i++)
100 {
101 for (int j=1 ;j<=n ;j++)
102 scanf("%d",&an[i][j]);
103 }
104 from=1;
105 to=2*n*n;
106 for (int i=1 ;i<=n ;i++)
107 {
108 for (int j=1 ;j<=n ;j++)
109 {
110 int u=(i-1)*n+j;
111 int v=(i-1)*n+j+n*n;
112 add(u,v,1,an[i][j]);
113 if (j+1<=n) add(v,u+1,1,0);
114 if (i+1<=n) add(v,i*n+j,1,0);
115 }
116 }
117 add(from,from+n*n,1,an[1][1]);
118 add(n*n,to,1,an[n][n]);
119 int sum=mincost();
120 printf("%d
",sum);
121 }
122 return 0;
123 }