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.
32 1 16 982 1 16 9153 2 15 9 1521 22
Case 1: 3Case 2: 15Case 3: 36
题目大意:给定初始的n个山坡,并且有m个可加的山坡,选其中的不超过k个山坡来,放入n个山坡的两两中间。问最后加入不超过k个山坡的高度差之和的最大值。
思路:由题意可知,首先,n个山坡,那么有n-1个夹缝,在输入过程中求出初始的n-1个差值和ans(最后一定ANS>=ans),设源点S,汇点T,那么将n-1个夹缝与T连接容量为1;由于需要限流k,则S连接S'容量k, 那么接下来的难点在于怎么连接可加山坡与初始山坡,
题意中指明可加山坡高度0<=h<=30,可以处理出每个高度的山坡的个数num[i],那么我们只需连接S'->i,容量num[i],再将i->(n-1个夹缝)限流1.建图完成,跑一边最小费用最大流即可。
#include <iostream> #include <cstdio> #include <cstring> #include <set> #include <queue> #include <cmath> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f #define bug cout<<"bug\n" const int MAXN = 2007; const int MAXM = 1e6+7; int high[MAXN],num_sert[MAXN]; int dif_high[MAXN]; int n,m,k; struct node { int v,next,cost,flow,cap; } edge[MAXM]; int INDEX,N; int head[MAXN]; int pre[MAXN],dis[MAXN],vis[MAXN]; void add_edge(int u,int v,int cap,int cost) { edge[INDEX].v=v; edge[INDEX].cap=cap; edge[INDEX].cost=cost; edge[INDEX].next=head[u]; head[u]=INDEX++; edge[INDEX].v=u; edge[INDEX].cap=0; edge[INDEX].cost=-cost; edge[INDEX].next=head[v]; head[v]=INDEX++; } bool SPFA(int s,int t) { queue<int> q; while(!q.empty())q.pop(); memset(dis,INF,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(pre,-1,sizeof(pre)); dis[s]=0; vis[s]=1; q.push(s); int M=INF; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u]; i+1; i=edge[i].next) { int v=edge[i].v; if(edge[i].cap &&dis[v]>dis[u]+edge[i].cost) { dis[v]=dis[u]+edge[i].cost; pre[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } } if(pre[t]==-1)return 0; return 1; } 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].v ]) { if(Min>edge[i].cap) Min=edge[i].cap; }*/ for(int i=pre[t]; i+1; i=pre[ edge[i^1].v ]) { edge[i].cap-=1; edge[i^1].cap+=1; cost+=edge[i].cost; } flow+=Min; } return flow; } int main() { int T,cas=0,ans; scanf("%d",&T); while(T--) { memset(num_sert,0,sizeof(num_sert)); memset(head,-1,sizeof(head)); ans=INDEX=0; scanf("%d%d%d",&n,&m,&k); for(int i=0; i<n; ++i) { scanf("%d",&high[i]); if(i) { int d=abs(high[i]-high[i-1]); ans+=d; } } int p; for(int i=0; i<m; ++i) { scanf("%d",&p); num_sert[p]++; } // start:31 end:33+n add_edge(31,32,k,0); for(int i=0; i<=30; ++i) if(num_sert[i]) { add_edge(32,i,num_sert[i],0); for(int j=1; j<n; ++j) add_edge(i,32+j,num_sert[i],-(abs(i-high[j])+abs(i-high[j-1])-abs(high[j]-high[j-1]))); } for(int i=33; i<33+n-1; ++i) add_edge(i,33+n,1,0); int temp=0; minCostMaxflow(31,33+n,temp); printf("Case %d: %d\n",++cas,ans-temp); } return 0; }