解题思路
使用记忆化搜索:
- 定义 表示区间 构造回文的最小和
- 递归处理:
- 如果 ,返回单个数字
- 如果 ,返回
- 如果两端相等,递归处理中间部分
- 如果两端不等,取两种方案的最小值
代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<vector<int>> matrix;
int findMinSum(vector<int>& arr, int left, int right) {
// 基础情况
if (left == right) {
return arr[left];
}
if (left > right) {
return 0;
}
// 如果已经计算过
if (matrix[left][right] != 0) {
return matrix[left][right];
}
// 如果两端相等
if (arr[left] == arr[right]) {
matrix[left][right] = 2 * arr[left] + findMinSum(arr, left + 1, right - 1);
} else {
// 取两种方案的最小值
int useLeft = findMinSum(arr, left + 1, right) + 2 * arr[left];
int useRight = findMinSum(arr, left, right - 1) + 2 * arr[right];
matrix[left][right] = min(useLeft, useRight);
}
return matrix[left][right];
}
int main() {
// 读取输入
int n;
cin >> n;
vector<int> arr(n);
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
// 初始化记忆数组
matrix.resize(n, vector<int>(n, 0));
// 计算结果
int result = findMinSum(arr, 0, n-1);
cout << result << endl;
return 0;
}
import java.util.*;
public class Main {
static int[][] matrix;
static int findMinSum(int[] arr, int left, int right) {
// 基础情况
if (left == right) {
return arr[left];
}
if (left > right) {
return 0;
}
// 如果已经计算过
if (matrix[left][right] != 0) {
return matrix[left][right];
}
// 如果两端相等
if (arr[left] == arr[right]) {
matrix[left][right] = 2 * arr[left] + findMinSum(arr, left + 1, right - 1);
} else {
// 取两种方案的最小值
int useLeft = findMinSum(arr, left + 1, right) + 2 * arr[left];
int useRight = findMinSum(arr, left, right - 1) + 2 * arr[right];
matrix[left][right] = Math.min(useLeft, useRight);
}
return matrix[left][right];
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 读取输入
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
// 初始化记忆数组
matrix = new int[n][n];
// 计算结果
int result = findMinSum(arr, 0, n-1);
System.out.println(result);
}
}
def find_min_sum(arr, left, right, matrix):
# 基础情况
if left == right:
return arr[left]
if left > right:
return 0
# 如果已经计算过
if matrix[left][right] != 0:
return matrix[left][right]
# 如果两端相等
if arr[left] == arr[right]:
matrix[left][right] = 2 * arr[left] + find_min_sum(arr, left + 1, right - 1, matrix)
else:
# 取两种方案的最小值
use_left = find_min_sum(arr, left + 1, right, matrix) + 2 * arr[left]
use_right = find_min_sum(arr, left, right - 1, matrix) + 2 * arr[right]
matrix[left][right] = min(use_left, use_right)
return matrix[left][right]
def solve():
# 读取输入
n = int(input())
arr = list(map(int, input().split()))
# 初始化记忆数组
matrix = [[0] * n for _ in range(n)]
# 计算结果
result = find_min_sum(arr, 0, n-1, matrix)
print(result)
if __name__ == "__main__":
solve()
算法及复杂度
- 算法:记忆化搜索(动态规划)
- 时间复杂度:,其中 是数组长度
- 空间复杂度:,用于存储记忆数组