题目描述
Xiao Ming recently designs a little game, in front of player there are N small hillsides put in order, now Xiao Ming wants to increase some hillsides to block the player, so he prepared another M hillsides, but he does not hope it will be too difficult,so only K in M hillsides are selected to add at most. Paying attention to the original N hillsides, between each two can add only one hillside. Xiao Ming expects players from the starting place to reach the destination in turn and passes all the hillsides to make his distance travelled longest. Please help Xiao Ming how to add the hillsides that he prepared. Note: The distance between two hillsides is the absolute value of their height difference.
输入
The first line of input is T, (1 <= T <= 100) the number of test cases. Each test case starts with three integers N,M,K (2 <= N <= 1000, 1 <= M <= 1000, 1 <= K <= M and 1 <= K < N), which means that the number of original hillsides, the number of hillsides Xiao Ming prepared and The number of most Xiao Ming can choose from he prepared. Then follow two lines, the first line contains N integers Xi (0 <= Xi <= 30), denoting the height of each original hillside, Note: The first integer is player’s starting place and the last integer is player’s destination. The second line contains M integers Yi (0 <= Yi <= 30), denoting the height of prepared each hillsides.
输出
For every test case, you should output "Case k: " first in a single line, where k indicates the case number and starts from 1. Then print the distance player can travel longest.
样例输入 Copy
3 2 1 1 6 9 8 2 1 1 6 9 15 3 2 1 5 9 15 21 22
样例输出 Copy
Case 1: 3 Case 2: 15 Case 3: 36
题意:
给出n个数,这n个数中有n-1个位置,在n-1个位置中插入k个数,k个数来自题目中给定的长度为m的数组,问插入k个数之后,两两之间的差值之和最大是多少:
思路:
最小费用最大流
预处理出没有处理的情况下的答案 ans,即相邻两数之差
首先设置一个辅助点 S',设置起点为S ,终点为T ,将起点和辅助点之间连入一条边,限制流量为k ,费用为0 ,即题目当中的选择的最大的数量限制,然后将 n−1 个空隙和辅助点接入容量为1,费用为0
对于网络的前半段已经连接成功,现在的问题是怎样连接已有的山坡和要加入的山坡,题目中给定高度的范围在 [0,30],所以说可以遍历高度,在 n−1 个间隔和t ( [ 0 , 30 ] ) 个高度之间建立连接,容量为1 ,费用为 −dis(最小费用类似最大生成树的处理方式),然后将t 个高度和终点T 建立容量为个数 (cnt[t]),费用为0的连接,最终求出最小费用最大流即可获得最小的费用 minCost,然后用 ans−minCost既是答案
建出来的的图应该是:
int a[maxn],b[33]; typedef pair<ll, ll> PLL; struct Edge { int u, v, cap, flow, cost; Edge(int _u, int _v, int _cap, int _flow, int _cost) { u = _u, v = _v, cap = _cap, flow = _flow, cost = _cost; } }; struct MinCostMaxFlow { int n, m; vector<Edge> edges; vector<int> G[maxn]; int vis[maxn], dis[maxn], p[maxn], a[maxn]; void init(int x) { this->n = x; for (int i = 0; i <= x; i++) G[i].clear(); edges.clear(); } void add(int u, int v, int cap, int cost) { edges.push_back(Edge(u, v, cap, 0, cost)); edges.push_back(Edge(v, u, 0, 0, -cost)); m = edges.size(); G[u].push_back(m - 2); G[v].push_back(m - 1); } bool BellmanFord(int s, int t, ll &flow, ll &cost) { for (int i = 0; i <= n; i++) dis[i] = 0x3f3f3f3f, vis[i] = 0; queue<int> que; que.push(s); dis[s] = 0, vis[s] = 0, p[s] = 0, a[s] = 0x3f3f3f3f; while (que.size()) { int u = que.front(); que.pop(); vis[u] = 0; /// not in the queue for (int i = 0; i < G[u].size(); i++) { int id = G[u][i]; Edge e = edges[id]; int to = e.v; if (e.cap > e.flow && dis[to] > dis[u] + e.cost) { dis[to] = dis[u] + e.cost; p[to] = id; a[to] = min(a[u], e.cap - e.flow); if (!vis[to]) { que.push(to); vis[to] = 1; } } } } if (dis[t] >= 0x3f3f3f3f) return false; flow += a[t]; cost += 1LL * dis[t] * 1LL * a[t]; for (int u = t; u != s; u = edges[p[u]].u) { edges[p[u]].flow += a[t]; edges[p[u] ^ 1].flow -= a[t]; } return true; } PLL MinCostAndMaxFlow(int s, int t) { ll flow = 0; ll cost = 0; while (BellmanFord(s, t, flow, cost)); return {flow, cost}; } } solve; int n, m, s, t, tm, tk; int main() { int _ = read; for(int I=1; I<=_; I++) { n = read,tm = read,tk = read; solve.init(n + 507); for(int i=0; i<=30; i++) b[i] = 0; for(int i=0; i<n; i++) a[i] = read; // for(int i=1; i<=n; i++) aa[i] = read; for(int i=1; i<=tm; i++) { int x = read; ++ b[x]; } ll ans = 0; for(int i=1; i<n; i++) { ans += abs(a[i] - a[i-1]); solve.add(0,i,1,0); for(int j=0; j<=30; j++) { if(b[j]) { ll dis = abs(a[i] - j) + abs(a[i-1]-j) - abs(a[i]-a[i-1]); solve.add(i,n+j,1,-dis); } } } int st = n + 33; int ed = st + 1; for(int i=0; i<=30; i++) { if(b[i]) solve.add(i+n,ed,b[i],0); } solve.add(st,0,tk,0); PLL tmp = solve.MinCostAndMaxFlow(st,ed); printf("Case %d: %lld\n",I,ans - tmp.second); } return 0; } /** 3 2 1 1 6 9 8 2 1 1 6 9 15 3 2 1 5 9 15 21 22 **/