Description
牛客网 2018校招真题 回文数组
Solving Ideas
方法一:
问题可以转化为求回文子序列的最大和(类似于求 最长回文子序列 ),则最终最优解为2 * sum - dp[0][a.length - 1]
,sum为数组a所有元素之和。回文子序列之和变大,能使为数组成为回文而补充的数字变小。
State:
dp[i][j]
: 表示a[i],...,a[j]
中的回文子序列的最大和
Initial State:
dp[i][i] = a[i]
State Transition:
if (a[i] == a[j]) dp[i][j] = dp[i + 1][j - 1] + 2 * a[i];
else dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
Time complexity :
O
(
n
2
)
O(n^2)
O(n2)
Space complexity :
O
(
n
2
)
O(n^2)
O(n2)
方法二:
区间动态规划:
for(int i = 0; i < n; i++) {
dp[i][i] = 初始值;
}
for(int len = 2; len <= n; len++) //区间长度
for(int i = 0; i + len <= n; i++) { //枚举起点
int j = i + len - 1; //区间终点
for(int k = i; k < j; k++) { //枚举分割点
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j] + w[i][j]);
}
}
}
其实也就是由小区间的最优解来构造更大区间的最优解
State:
dp[i][j]
: 表示区间[i, j]的最优解
Initial State:
dp[i][i] = a[i]
;
State Transition:
if (a[i] == a[j]) dp[i][j] = dp[i + 1][j - 1] + 2 * a[i];
else dp[i][j] = max(dp[i + 1][j] + 2 * a[i], dp[i][j - 1] + 2 * a[j]);
Time complexity :
O
(
n
2
)
O(n^2)
O(n2)
Space complexity :
O
(
n
2
)
O(n^2)
O(n2)
Solution
方法一代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Dynamic Programming
*
* State:
* dp[i][j]: 表示a[i],...,a[j]中的回文子序列的最大和
*
* Initial State:
* dp[i][i] = a[i]
*
* State Transition:
* if (a[i] == a[j]) dp[i][j] = dp[i + 1][j - 1] + 2 * a[i];
* else dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
*
* @author wylu
*/
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
String[] strs = br.readLine().split(" ");
int[] a = new int[n];
long sum = 0;
for (int i = 0; i < n; i++) {
a[i] = Integer.parseInt(strs[i]);
sum += a[i];
}
long[][] dp = new long[n][n];
for (int i = a.length - 1; i >= 0; i--) {
dp[i][i] = a[i];
for (int j = i + 1; j < a.length; j++) {
if (a[i] == a[j]) dp[i][j] = dp[i + 1][j - 1] + 2 * a[i];
else dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
}
}
System.out.println(2 * sum - dp[0][n - 1]);
}
}
方法二代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Dynamic Programming
*
* State:
* dp[i][j]: 表示区间[i, j]的最优解
*
* Initial State:
* dp[i][i] = a[i];
*
* State Transition:
* if (a[i] == a[j]) dp[i][j] = dp[i + 1][j - 1] + 2 * a[i];
* else dp[i][j] = max(dp[i + 1][j] + 2 * a[i], dp[i][j - 1] + 2 * a[j]);
*
* @author wylu
*/
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
String[] strs = br.readLine().split(" ");
int[] a = new int[n];
long[][] dp = new long[n][n];
for (int i = 0; i < n; i++) {
a[i] = Integer.parseInt(strs[i]);
dp[i][i] = a[i];
}
for (int len = 2; len <= n; len++) {
for (int i = 0; i + len <= n; i++) {
int j = i + len - 1;
if (a[i] == a[j]) dp[i][j] = dp[i + 1][j - 1] + 2 * a[i];
else dp[i][j] = Math.min(dp[i + 1][j] + 2 * a[i], dp[i][j - 1] + 2 * a[j]);
}
}
System.out.println(dp[0][n - 1]);
}
}