Vijos1653 疯狂的方格取数
描述
在一个宽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 }