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 }
?