​评测地址​

题目描述

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个数之后,两两之间的差值之和最大是多少:

思路:
​​​链接​​​ 最小费用最大流
预处理出没有处理的情况下的答案[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_最小费用最大流,即相邻两数之差
首先设置一个辅助点[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_最大流_02,设置起点为[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_ide_03,终点为[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_ide_04,将起点和辅助点之间连入一条边,限制流量为[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_最小费用最大流_05,费用为[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_ide_06,即题目当中的选择的最大的数量限制,然后将[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_i++_07个空隙和辅助点接入容量为[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_最小费用最大流_08,费用为[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_ide_06
对于网络的前半段已经连接成功,现在的问题是怎样连接已有的山坡和要加入的山坡,题目中给定高度的范围在[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_最小费用最大流_10,所以说可以遍历高度,在[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_i++_07个间隔和[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_i++_12[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_i++_13个高度之间建立连接,容量为[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_最小费用最大流_08,费用为[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_最小费用最大流_15(最小费用类似最大生成树的处理方式),然后将[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_i++_12个高度和终点[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_ide_04建立容量为个数[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_最小费用最大流_18,费用为0的连接,最终求出最小费用最大流即可获得最小的费用[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_最大流_19,然后用[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_ide_20既是答案

建出来的的图应该是:

[SDUT 2414] | 山东省第三届省赛 An interesting game | 最小费用最大流_ide_21

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

**/