[Vijos 1143]三取方格数
Description
设有N*N的方格图,我们将其中的某些方格填入正整数,
而其他的方格中放入0。
某人从图得左上角出发,可以向下走,也可以向右走,直到到达右下角。
在走过的路上,他取走了方格中的数。(取走后方格中数字变为0)
此人从左上角到右下角共走3次,试找出3条路径,使得取得的数总和最大。
Input
第一行:N (4<=N<=20)
接下来一个N*N的矩阵,矩阵中每个元素不超过80,不小于0
Output
一行,表示最大的总和。
Sample Input
4
1 2 3 4
2 1 3 4
1 2 3 4
1 3 2 4
Sample Output
39
题解(转载)
$DP$好题。
这里给出费用流的做法:
拆点建图,每一个点都拆成两个点,在这里就称为出点和入点。
出点和入点建两条边,一条费用为$s[i][j]$,流量为$1$;一条费用为$0$,流量为$inf$。(分别表示选择这个点和从这个点上经过)
将$(i,j)$的出点分别和$(i+1,j)$$(i,j+1)$的入点建边,流量为$inf$,费用为$0$。(表示行进)
跑一边最大费用最大流就可以了。
1 #include <set> 2 #include <map> 3 #include <ctime> 4 #include <cmath> 5 #include <queue> 6 #include <stack> 7 #include <vector> 8 #include <cstdio> 9 #include <string> 10 #include <cstring> 11 #include <cstdlib> 12 #include <iostream> 13 #include <algorithm> 14 #define LL long long 15 #define Max(a, b) ((a) > (b) ? (a) : (b)) 16 #define Min(a, b) ((a) < (b) ? (a) : (b)) 17 using namespace std; 18 const int INF = ~0u>>1; 19 20 int n; 21 int a[25][25]; 22 struct tt{ 23 int to, cost, next, cap; 24 }edge[5005]; 25 int path[1005], top = -1; 26 void Add(int u, int v, int cost, int cap); 27 int sta = 999, fin = 1000; 28 int min_cost_flow(); 29 int SPFA(); 30 31 int main(){ 32 memset(path, -1, sizeof(path)); 33 scanf("%d", &n); 34 for (int i = 0; i < n; i++) 35 for (int j = 0; j < n; j++) 36 scanf("%d", &a[i][j]); 37 for (int i = 0; i < n; i++) 38 for (int j = 0; j < n; j++){ 39 Add(i*n+j, (i+n)*n+j, a[i][j], 1); 40 Add(i*n+j, (i+n)*n+j, 0, INF); 41 if (i != n-1) Add((i+n)*n+j, (i+1)*n+j, 0, INF); 42 if (j != n-1) Add((i+n)*n+j, i*n+j+1, 0, INF); 43 } 44 Add(sta, 0, 0, 3); 45 Add((2*n-1)*n+n-1, fin, 0 ,3); 46 printf("%d\n", min_cost_flow()); 47 return 0; 48 } 49 50 void Add(int u, int v, int cost, int cap){ 51 edge[++top].to = v; 52 edge[top].cost = cost; 53 edge[top].cap = cap; 54 edge[top].next = path[u]; 55 path[u] = top; 56 edge[++top].to = u; 57 edge[top].cost = -cost; 58 edge[top].cap = 0; 59 edge[top].next = path[v]; 60 path[v] = top; 61 } 62 int min_cost_flow(){ 63 int tolcost = 0; 64 int tmp; 65 while (tmp = SPFA()) tolcost += tmp; 66 return tolcost; 67 } 68 int SPFA(){ 69 int dist[1005]; 70 memset(dist, 128, sizeof(dist)); dist[sta] = 0; dist[fin] = -INF; 71 bool vis[1005] = {0}; vis[sta] = 1; 72 queue<int>Q; 73 while (!Q.empty()) Q.pop(); 74 Q.push(sta); 75 int pre[1005] = {0}; 76 while (!Q.empty()){ 77 int u = Q.front(); Q.pop(); vis[u]=0; 78 for (int i = path[u]; i != -1; i = edge[i].next){ 79 int v = edge[i].to; 80 if (dist[v] < dist[u]+edge[i].cost && edge[i].cap > 0){ 81 dist[v] = dist[u]+edge[i].cost; 82 pre[v] = i; 83 if (!vis[v]){ 84 vis[v] = 1; 85 Q.push(v); 86 } 87 } 88 } 89 } 90 if (dist[fin] == -INF) return 0; 91 int minflow = INF; 92 for (int i = fin; i != sta; i = edge[pre[i]^1].to) 93 minflow = Min(minflow, edge[pre[i]].cap); 94 for (int i = fin; i != sta; i = edge[pre[i]^1].to) 95 edge[pre[i]].cap -= minflow, 96 edge[pre[i]^1].cap += minflow; 97 return dist[fin]; 98 }
博主蒟蒻,随意转载。但必须附上原文链接:http://www.cnblogs.com/NaVi-Awson/,否则你会终生找不到妹子!!!