Vijos1653 疯狂的方格取数

题目链接:https://vijos.org/p/1653

描述

在一个宽M,长N的矩阵中,请你编一个程序,n次从矩阵的左上角走到矩阵的右下角,每到一处,就取走该处的数字,请你选择一
种走法使取得的数字的和最大,并输出其最大值。其中:3<=M<=20 M<=N<=100 1<=n<=10

K路方格取数的费用流做法

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <queue>
 6 #define rep(i,l,r) for(int i=l; i<=r; i++)
 7 #define clr(x,y) memset(x,y,sizeof(x))
 8 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
 9 using namespace std;
10 const int INF = 0x3f3f3f3f;
11 const int maxn = 110;
12 const int maxm = 30;
13 inline int read(){
14     int ans = 0, f = 1;
15     char c = getchar();
16     for(; !isdigit(c); c = getchar())
17     if (c == '-') f = -1;
18     for(; isdigit(c); c = getchar())
19     ans = ans * 10 + c - '0';
20     return ans * f;
21 }
22 struct Edge{
23     Edge *pre,*rev; int to,cap,cost;
24 }edge[maxn*maxm*4],*last[maxn*maxm*2],*pre[maxn*maxm*2],*pt;
25 int n,m,k,N,S,T,pos[maxn][maxm][2],w[maxn][maxm],d[maxn*maxm*2];
26 bool isin[maxn*maxm*2];
27 queue <int> q;
28 inline void add(int x,int y,int z,int w){
29     pt->pre = last[x]; pt->to = y; pt->cap = z; pt->cost = w; last[x] = pt++;
30     pt->pre = last[y]; pt->to = x; pt->cap = 0; pt->cost = -w; last[y] = pt++;
31     last[x]->rev = last[y]; last[y]->rev = last[x];
32 }
33 bool spfa(){
34     clr(isin,0); isin[S] = 1; q.push(S);
35     clr(d,INF); d[S] = 0;
36     while (!q.empty()){
37         int now = q.front(); q.pop(); isin[now] = 0;
38         travel(now){
39             if (p->cap && d[p->to] > d[now] + p->cost){
40                 d[p->to] = d[now] + p->cost;
41                 pre[p->to] = p;
42                 if (!isin[p->to]){
43                     isin[p->to] = 1; q.push(p->to);
44                 }
45             }
46         }
47     }
48     return d[T] != INF;
49 }
50 int mincost(){
51     int ret = 0, x = INF;
52     while (spfa()){
53         for(Edge *p = pre[T]; p; p = pre[p->rev->to]) x = min(x,p->cap);
54         for(Edge *p = pre[T]; p; p = pre[p->rev->to]){
55             ret += x * p->cost; p->cap -= x; p->rev->cap += x;
56         }
57     }
58     return ret;
59 }
60 int main(){
61     k = read(); m = read(); n = read();
62     clr(last,0); pt = edge;
63     rep(i,1,n){
64         rep(j,1,m){
65             w[i][j] = read();
66             pos[i][j][0] = ++N; pos[i][j][1] = ++N;
67             add(pos[i][j][0],pos[i][j][1],1,-w[i][j]);
68             add(pos[i][j][0],pos[i][j][1],INF,0);
69         }
70     }
71     S = ++N; T = ++N;
72     add(S,pos[1][1][0],k,0); add(pos[n][m][1],T,k,0);
73     rep(i,1,n) rep(j,1,m){
74         if (i + 1 <= n) add(pos[i][j][1],pos[i+1][j][0],INF,0);
75         if (j + 1 <= m) add(pos[i][j][1],pos[i][j+1][0],INF,0);
76     }
77     printf("%d\n",-mincost());
78     return 0;
79 }
View Code

posted on 2016-03-21 14:38  ACMICPC  阅读(296)  评论(0编辑  收藏  举报

导航