hdu 4960 Another OCD Patient(기억화)

6180 단어
제목 링크: hdu 4960 Another OCD Patient
제목의 뜻: 길이가 n인 서열을 정한 다음에 n개의 수ai를 제시하여 i개의 수를 합성하는 대가를 나타낸다.매번 연속된 하위 서열을 하나의 수로 합칠 수 있다. 즉, 서열의 각 항목의 합이다.주어진 길이 n의 서열을 회문열로 바꾸고 숫자는 한 번만 합성할 수 있도록 요구합니다.
문제풀이 방향: dp[l][r]는 l에서 r로 화합되는 최소 대가를 나타낸다. dp[l][r]=min(r-3l+1),val(r-3i+1)+val(j-3l+1)+dp[j+1][i-1]))))),i가 1씩 줄어들 때마다 대응하는 j가 반드시 커진다는 점은 대부분의 매거량을 줄일 수 있다.
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long ll;

const int maxn = 5005;

int N, arr[maxn], dp[maxn][maxn];
ll x, val[maxn];

inline ll getval (int l, int r) {
    return val[r] - val[l-1];
}

void init () {
    memset(dp, -1, sizeof(dp));

    val[0] = 0;
    for (int i = 1; i <= N; i++) {
        scanf("%I64d", &x);
        val[i] = val[i-1] + x;
    }

    for (int i = 1; i <= N; i++)
        scanf("%d", &arr[i]);
}

int solve (int l, int r) {

    if (l > r)
        return 0;

    if (dp[l][r] != -1)
        return dp[l][r];


    int& ret = dp[l][r];
    ret = arr[r-l+1];

    int mv = l;

    for (int i = r; i > l; i--) {
        ll u = getval(i, r);

        while (getval(l, mv) < u && mv < i)
            mv++;

        if (mv >= i)
            break;

        if (getval(l, mv) == u)
            ret = min(ret, arr[r-i+1] + arr[mv-l+1] + solve(mv+1, i-1));
    }
    return ret;
}

int main () {
    while (scanf("%d", &N) == 1 && N) {
        init();
        printf("%d
"
, solve(1, N)); } return 0; }

좋은 웹페이지 즐겨찾기