1033 蚯蚓的遊戲問題
在一塊梯形田地上,一群蚯蚓在做收集食物遊戲。蚯蚓們把梯形田地上的食物堆積整理如下:
a(1,1) a(1,2)…a(1,m)
a(2,1) a(2,2) a(2,3)…a(2,m) a(2,m+1)
a(3,1) a (3,2) a(3,3)…a(3,m+1) a(3,m+2)
……
a(n,1) a(n,2) a(n,3)… a(n,m+n-1)
它們把食物分成n行,第1行有m堆的食物,每堆的食物量分別是a(1,1),a(1,2),…,a(1,m);
第2行有m+1堆食物,每堆的食物量分別是a(2,1),a(2,2),…, a(2,m+1);以下依次有m+2堆、m+3堆、…m+n-1堆食物。
現在蚯蚓們選擇了k條蚯蚓來測試它們的合作能力(1≤ k ≤m)。測試法如下:第1條蚯蚓從第1行選擇一堆食物,然後往左下或右下爬,並收集1堆食物,例如從a(1,2)只能爬向a(2,2) 或a(2,3),而不能爬向其它地方。接下來再爬向下一行收集一堆食物,直到第n行收集一堆食物。第1條蚯蚓所收集到的食物量是它在每一行所收集的食物量之和;第2條蚯蚓也從第1行爬到第n行,每行收集一堆食物,爬的方法與第1條蚯蚓相類似,但不能碰到第1條蚯蚓所爬的軌跡;一般地,第i 條蚯蚓從第1行爬到第 n行,每行收集一堆食物,爬的方法與第1條蚯蚓類似,但不能碰到前 I-1 條蚯蚓所爬的軌跡。這k條蚯蚓應該如何合作,才能使它們所收集到的食物總量最多?收集到的食物總量可代表這k條蚯蚓的合作水平。
- ?編程任務:
給定上述梯形m、n和k的值(1≤k≤m≤30;1≤n≤30)以及梯形中每堆食物的量(小於10的非整數),編程計算這k條蚯蚓所能收集到的食物的最多總量。
輸入描述 Input Description輸入數據由文件名為INPUT1.*的文本文件提供,共有n+1行。每行的兩個數據之間用一個空格隔開。
●第1行是n、m和k的值。
- 接下來的n行依次是梯形的每一行的食物量a(i,1),a(i,2),…,a(i,m+i-1),i=1,2,…,n。
程序運行結束時,在屏幕上輸出k蚯蚓條所能收集到的食物的最多總量。
3 2 2
1 2
5 0 2
1 10 0 6
樣例輸出 Sample Output26
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<sstream> #include<algorithm> #include<queue> #include<deque> #include<iomanip> #include<vector> #include<cmath> #include<map> #include<stack> #include<set> #include<functional> #include<memory> #include<list> #include<string> using namespace std; typedef long long LL; typedef unsigned long long ULL; /* 每個點只過一次 拆點建邊(容量為1,費用為權值) k條蚯蚓,從源點流出容量為k 源點向入點加邊(容量為1,費用為0) 出點向匯點加邊(容量為1,費用為0) */ const int MAXN = 10000; const int MAXM = 100000; const int INF = 0x3f3f3f3f; struct Edge { int to, next, cap, flow, cost; }edge[MAXM]; int head[MAXN], tol; int pre[MAXN], dis[MAXN]; bool vis[MAXN]; int N;//節點總個數,節點編號從0~N-1 void init(int n) { N = n; tol = 0; memset(head, -1, sizeof(head)); } void addedge(int u, int v, int cap, int cost) { edge[tol].to = v; edge[tol].cap = cap; edge[tol].cost = cost; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = 0; edge[tol].cost = -cost; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++; } bool spfa(int s, int t) { queue<int>q; for (int i = 0; i < N; i++) { dis[i] = INF; vis[i] = false; pre[i] = -1; } dis[s] = 0; vis[s] = true; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost) { dis[v] = dis[u] + edge[i].cost; pre[v] = i; if (!vis[v]) { vis[v] = true; q.push(v); } } } } if (pre[t] == -1)return false; else return true; } //返回的是最大流,cost存的是最小費用 int minCostMaxflow(int s, int t, int &cost) { int flow = 0; cost = 0; while (spfa(s, t)) { int Min = INF; for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) { if (Min > edge[i].cap - edge[i].flow) Min = edge[i].cap - edge[i].flow; } for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) { edge[i].flow += Min; edge[i ^ 1].flow -= Min; cost += edge[i].cost * Min; } flow += Min; } return flow; } int m, n, k; int val[MAXN]; int Next[MAXN][2]; int main() { ios::sync_with_stdio(0); cin >> n >> m >> k; int cnt = 1; for (int i = 0; i < n; i++) { for (int j = 0; j < m + i; j++) { if (i != n - 1) { Next[cnt][0] = cnt + m + i; Next[cnt][1] = Next[cnt][0] + 1; } cin >> val[cnt++]; } } int num = cnt - 1; init(2 * num + 3); for (int i = 1; i <= cnt; i++) { addedge(i, i + num, 1, -val[i]); //cout << val[i] << endl; } for (int i = 1; i <= m; i++) { addedge(0, i, 1, 0); //cout << val[i] << endl; } for (int i = num, tmp = 1; tmp < m + n; i--, tmp++) { addedge(i + num, 2 * num + 1, 1, 0); //cout << val[i] << endl; } for (int i = 1; i <= cnt; i++) { if (Next[i][0] == 0 && Next[i][1] == 0) break; addedge(i + num, Next[i][0], 1, 0); addedge(i + num, Next[i][1], 1, 0); } addedge(2 * num + 2, 0, k, 0); int ans; minCostMaxflow(2 * num + 2, 2 * num + 1, ans); cout << -ans << endl; return 0; }
1033 蚯蚓的遊戲問題