题目
小易有n块砖块,每一块砖块有一个高度。小易希望利用这些砖块堆砌两座相同高度的塔。为了让问题简单,砖块堆砌就是简单的高度相加,某一块砖只能使用在一座塔中一次。小易现在让能够堆砌出来的两座塔的高度尽量高,小易能否完成呢。
- 输入描述:
输入包括两行:第一行为整数n(1 ≤ n ≤ 50),即一共有n块砖块,第二行为n个整数,表示每一块砖块的高度height[i] (1 ≤ height[i] ≤ 500000) - 输出描述:
如果小易能堆砌出两座高度相同的塔,输出最高能拼凑的高度,如果不能则输出-1。保证答案不大于500000。 - 输入例子:
3
2 3 5 - 输出例子:
5
分析1
不能按照
0−1
背包问题去解,因为不能保证堆砌的两个塔高度相等。砖块
bk for k=0∼n−1
。定义
h[i,j]
为使用前
i
块砖能够堆砌的低塔高度,
h[i,j]=⎧⎩⎨⎪⎪⎪⎪⎪⎪0,−∞,max⎧⎩⎨⎪⎪⎪⎪h[i−1,j],h[i−1,j+bi]+bi,h[i−1,bi−j]+bi−j,h[i−1,j−bi],1.丢弃第i块砖2.第i块砖放在低塔仍为低塔3.第i块砖放在低塔变为高塔4.第i块砖放在高塔⎫⎭⎬⎪⎪⎪⎪,i,j=0i=0,j≠0i>0
当
i=0
时表示还没有砖块,高度差
j
一定为0,
代码1
import java.util.Scanner;
public class Main {
static void tower(int[] bricks, int[][] h, int n, int sum) {
h[0][0] = 0;
for (int i = 1; i <= sum; i++) {
h[0][i] = Integer.MIN_VALUE;
}
for (int i = 1; i <= n; i++) {
int b = bricks[i - 1];
for (int j = 0; j <= sum; j++) {
h[i][j] = h[i - 1][j];
if (j + b <= sum) {
h[i][j] = Math.max(h[i][j], h[i - 1][j + b] + b);
}
if (b - j >= 0) {
h[i][j] = Math.max(h[i][j], h[i - 1][b - j] + b - j);
} else {
h[i][j] = Math.max(h[i][j], h[i - 1][j - b]);
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] bricks = new int[n];
int sum = 0;
for (int i = 0; i < n; i++) {
bricks[i] = sc.nextInt();
sum = sum + bricks[i];
}
int[][] h = new int[n + 1][sum + 1];
tower(bricks, h, n, sum);
System.out.println(h[n][0] > 0 ? h[n][0] : -1);
}
}
分析2
另一种简单的解法是定义
h[i,j]
为使用前
i
块砖能够堆砌的一个塔的高度,
h[i,j]=⎧⎩⎨⎪⎪⎪⎪0,−∞,max⎧⎩⎨⎪⎪h[i−1,j],h[i−1,j−bi],h[i−1,j+bi]+bi,1.丢弃第i块砖2.第i块砖放在另一塔3.第i块砖放在这个塔⎫⎭⎬⎪⎪,i=0,j=sum(bk)i=0,j≠sum(bk)i>0
代码2
import java.util.Scanner;
public class Main {
static void tower(int[] bricks, int[][] h, int n, int sum) {
for (int i = 0; i < 2 * sum + 1; i++) {
h[0][i] = Integer.MIN_VALUE;
}
h[0][sum] = 0;
for (int i = 1; i <= n; i++) {
int b = bricks[i - 1];
for (int j = 0; j < 2 * sum + 1; j++) {
h[i][j] = h[i - 1][j];
if (j - b >= 0) {
h[i][j] = Math.max(h[i][j], h[i - 1][j - b]);
}
if (j + b < 2 * sum + 1) {
h[i][j] = Math.max(h[i][j], h[i - 1][j + b] + b);
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] bricks = new int[n];
int sum = 0;
for (int i = 0; i < n; i++) {
bricks[i] = sc.nextInt();
sum = sum + bricks[i];
}
int[][] h = new int[n + 1][2 * sum + 1];
tower(bricks, h, n, sum);
System.out.println(h[n][sum] > 0 ? h[n][sum] : -1);
}
}