对决 - Head to Head Showdown - DP
对决
时间限制:最多40个用例,1秒(C/C++),1.5秒(Java)/内存限制:256 MB(Stack 1 MB)
你负责组织A队和B队之间的围棋比赛。两支队伍决定在队员之间进行一对一比赛,但发现A队有N名队员,B队有N+1名队员。(同一队员不能参加两次比赛,而为了一对一比赛,B队中必然需要排除一名队员。)
假设已知两队队员的各自实力。为了最大程度的进行公平比赛,在一对一比赛中,双方队员之间的实力差异的绝对值总和应为最小。
例如,假设A队有五名队员,实力分别为2、6、4、10、4;B队有六名队员,实力分别为 7、9、1、6、5、10。此时,排除B队中实力为9的队员后,按照如下一样成对的进行比赛时,实力差异的绝对值总和为5,这将成为最小的情况。但如下方式并非是唯一的方式。(括号内第一个数值为A队队员的实力,第二个数值为B队队员的实力。)

接收两队队员的实力后,请编写出当B队伍中排除一名队员进行比赛时,两队队员实力差异的绝对值总和为最小的程序。
[限制条件]
1.A队的队员数N为介于1到300,000之间的整数。
2.实力值为介于1到1,000,000,000之间的整数。(注意整数的表示范围。)
[输入]
第一行给出测试用例数量T。随后给出T个测试用例。各个用例的第一行给出A队的队员数N。下一行空格区分给出N个A队队员各自的实力。再下一行空格区分给出N+1个B队队员各自的实力。
[输出]
各个测试用例的答案按照顺序标准输出。对每个用例输出“#x”(x为测试用例编号,从1开始),加一个空格后(不包含引号),输出题目中要求的最小的实力差异绝对值总和。
[输入输出 示例]
(输入)
3
5
2 6 4 10 4
7 9 1 6 5 10
8
3 1 8 4 2 7 9 6
1 4 5 10 6 5 3 8 8
1
1
1000000000 1000000000
(输出)
#1 5
#2 5
#3 999999999
思路分析:
求实力差最小,那么肯定是小的减小的,大的减大的,所以,要对两队实力先进行排序,然后再进行计算
B队多一个人,需要去掉一个人,但是我们不知道去掉哪个是最优解,那么就把所有人都去掉试一次,典型的动态规划问题
dp[i]表示去掉第i个人后,两队实力的绝对值之和
dp[0] = Math.abs(A[0]-B[1]) + Math.abs(A[1]-B[2]) + Math.abs(A[2]-B[3]) +....
dp[1] = Math.abs(A[0]-B[0]) + Math.abs(A[1]-B[2]) + Math.abs(A[2]-B[3]) +....
dp[2] = Math.abs(A[0]-B[0]) + Math.abs(A[1]-B[1]) + Math.abs(A[2]-B[3]) +....
则: dp[2] - dp[1] = Math.abs(A[1]-B[1]) - Math.abs(A[1]-B[2]);
递推公式: dp[i] = dp[i-1] + Math.abs(A[i-1]-B[i-1]) - Math.abs(A[i-1]-B[i]);
package pro.dp;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
/**
* 对决
* @author XA-GDD
*
* 思路分析:
* 求实力差最小,那么肯定是小的减小的,大的减大的,所以,要对两队实力先进行排序,然后再进行计算
* B队多一个人,需要去掉一个人,但是我们不知道去掉哪个是最优解,那么就把所有人都去掉试一次,典型的动态规划问题
* dp[i]表示去掉第i个人后,两队实力的绝对值之和
* dp[0] = Math.abs(A[0]-B[1]) + Math.abs(A[1]-B[2]) + Math.abs(A[2]-B[3]) +....
* dp[1] = Math.abs(A[0]-B[0]) + Math.abs(A[1]-B[2]) + Math.abs(A[2]-B[3]) +....
* dp[2] = Math.abs(A[0]-B[0]) + Math.abs(A[1]-B[1]) + Math.abs(A[2]-B[3]) +....
* 则: dp[2] - dp[1] = Math.abs(A[1]-B[1]) - Math.abs(A[1]-B[2]);
* 递推公式: dp[i] = dp[i-1] + Math.abs(A[i-1]-B[i-1]) - Math.abs(A[i-1]-B[i]);
*/
public class HeadToHeadShowdown_0706 {
static int T,N;
static int _max_Nval = 300000;
static long [] A = new long[_max_Nval];
static long [] B = new long[_max_Nval+1];
static long [] dp = new long[_max_Nval+1];
static long ANS;
public static void main(String[] args) throws IOException {
System.setIn(new FileInputStream("D:\\workspace\\sw_pro\\test_case\\sample_input_0706.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
T = Integer.parseInt(st.nextToken());
for(int testCase = 1; testCase<= T;testCase++) {
Arrays.fill(A, 0);
Arrays.fill(B, 0);
Arrays.fill(dp, 0);
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
for(int i=0;i<N;i++) {
A[i] = Integer.parseInt(st.nextToken());
}
st = new StringTokenizer(br.readLine());
for(int i=0;i<=N;i++) {
B[i] = Integer.parseInt(st.nextToken());
}
Arrays.sort(A,0,N);
Arrays.sort(B,0,N+1);
//边界值dp[0]
for(int i=0;i<N;i++) {
dp[0] += Math.abs(A[i]-B[i+1]);
}
ANS=dp[0];
//根据递推公式求dp
for(int i=1;i<N;i++) {
dp[i] = dp[i-1] + Math.abs(A[i-1]-B[i-1]) - Math.abs(A[i-1]-B[i]);
ANS = Math.min(ANS, dp[i]);
}
System.out.printf("#%d %d\n", testCase,ANS);
}
}
}
浙公网安备 33010602011771号