NC20438. [SHOI2017]寿司餐厅
描述
输入描述
第一行包含两个正整数n,m,分别表示这家餐厅提供的寿司总数和计算寿司价格中使用的常数。第二行包含n个正整数,其中第k个数ak表示第k份寿司的代号。接下来n行,第i行包含n-i+1个整数,其中第j个数di,i+j-1表示吃掉寿司能获得的相应的美味度,具体含义见问题描述。N ≤ 100,Ai ≤ 1000
输出描述
输出共一行包含一个正整数,表示Kiana能获得的总美味度减去花费的总钱数的最大值。
示例1
输入:
3 1 2 3 2 5 -10 15 -10 15 15
输出:
12
说明:
【样例1说明】C++11(clang++ 3.9) 解法, 执行用时: 100ms, 内存消耗: 996K, 提交时间: 2019-07-19 10:34:27
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e2 + 5, INF = 0x3f3f3f3f, M = N * N * 2; #define ri register int // #define endl '\n' struct edge { int v, w; } G[M * 10]; int head[N * N + 2 * N], nxt[M * 10], n, m, tot = 1, S, T; int x[N]; void add(int u, int v, int w) { G[++tot] = {v, w}, nxt[tot] = head[u], head[u] = tot; G[++tot] = {u, 0}, nxt[tot] = head[v], head[v] = tot; } int L[N * N + 2 * N], cur[N * N + 2 * N]; bool bfs() { memset(L, 0, sizeof L); memcpy(cur, head, sizeof head); queue<int> q; q.push(S), L[S] = 1; while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; i; i = nxt[i]) { int v = G[i].v, w = G[i].w; if (!L[v] && w) L[v] = L[u] + 1, q.push(v); } } return L[T]; } int dfs(int u, int f) { if (u == T) return f; int flow = 0; for (int &i = cur[u]; i && f > flow; i = nxt[i]) { int v = G[i].v, w = G[i].w; if (L[v] != L[u] + 1 || !w) continue; int d = dfs(v, min(f - flow, w)); if (!d) continue; flow += d, G[i].w -= d, G[i ^ 1].w += d; } return flow; } int maxflow() { int ans = 0; while (bfs()) ans += dfs(S, INF); return ans; } map<int, int> vis; int a[N][N], id[N][N]; int main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin >> n >> m; T = n * n + n * 2 + 2; int sum = 0, cnt = n; for (int i = 1; i <= n; i++) { cin >> x[i]; if (!vis[x[i]]) vis[x[i]] = ++cnt, add(cnt, T, x[i] * x[i] * m); add(i, vis[x[i]], INF), add(i, T, x[i]); } for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) id[i][j] = (i == j) ? i : ++cnt; for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) { cin >> a[i][j]; if (a[i][j] >= 0) add(S, id[i][j], a[i][j]), sum += a[i][j]; else add(id[i][j], T, -a[i][j]); if (i != j) add(id[i][j], id[i + 1][j], INF), add(id[i][j], id[i][j - 1], INF); } cout << sum - maxflow() << endl; }