2018秋招 搜狐 回文数组

来源:互联网 发布:中国网络在线教育 编辑:程序博客网 时间:2024/05/16 09:59

题目大意

给定一个正整数组成的数组,要求往数组中插入整数,使得插入后的数组是一个回文数组,并且回文数组的累加和最小。输出这个最小和。

栗子:
原始数组:1 2 3 1 2
插入后:1 2 1 3 1 2 1,数组和11.

输入:
包含2行,第一行数组元素个数n, 第二行为n个数组元素。 n <= 10000.
输出:
回文数组的最小和。

题目分析

暴力递归

找出原数组中累加和最大的回文子序列。待插入的数组元素就是回文子序列剩下的元素。

超时代码:

#include <bits/stdc++.h>using namespace std;bool check(vector<int>& vec) {    int l = 0, r = vec.size() - 1;    while (l <= r) {        if (vec[l] != vec[r]) return false;        l++;        r--;    }    return true;}void helper(vector<vector<int>>& vv, vector<int>& res, vector<int> vec, int depth) {    if (depth == vec.size()) {        if (check(res)) vv.push_back(res);        return;    }    res.push_back(vec[depth]);    helper(vv, res, vec, depth + 1);    res.pop_back();    helper(vv, res, vec, depth + 1);}int main() {    int L;    while (cin >> L) {        long long sum = 0;        vector<int> vec(L, 0);        for (int i = 0; i < L; ++i) cin >> vec[i], sum += vec[i];        vector<vector<int>> vv;        vector<int> res;        helper(vv, res, vec, 0);        int maxRes = 0;        long long partSum = 0;        for (int i = 0; i < vv.size(); ++i) {            if (vv[i].size() >= maxRes) {                long long tmpSum = 0;                for (int k = 0; k < vv[i].size(); ++k) tmpSum += vv[i][k];                if (tmpSum > partSum) {                    partSum = tmpSum;                    maxRes = i;                }            }        }        cout << partSum << endl;        cout << sum + sum - partSum << endl;    }    return 0;}

动态规划

传统的求最长回文子序列的问题可以转化为LCS(最长公共子序列问题)
本题中,我们沿用这个思路。

求累加和最大的公共子序列

状态方程和最长公共子序列的状态方程变化不大。

dp[i][j] = dp[i - 1][j - 1] + a[i], a[i] == b[j]
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]), a[i] != b[j];
// a[]原始数组,b[]为反转数组

AC代码:

#include <bits/stdc++.h>using namespace std;long long a[10010];long long b[10010];long long dp[10010][10010];int main() {    int n;    while (cin >> n) {        long long sum = 0;        for (int i = 1; i <= n; i++) {            cin >> a[i];            b[n + 1 - i] = a[i];            sum += a[i];        }        memset(dp, 0, sizeof(dp));        for (int i = 1; i <= n; ++i) {            for (int j = 1; j <= n; ++j) {                if (a[i] == b[j]) dp[i][j] = dp[i - 1][j - 1] + a[i];                else dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);            }        }        cout << sum + sum - dp[n][n] << endl;    }    return 0;}
原创粉丝点击