HDU 4960 Another OCD Patient 区间dp

本文介绍了一种区间动态规划算法的应用实例,通过一个具体的题目来详细解释如何使用区间DP解决复杂问题,并提供了完整的C++实现代码。

区间dp。。

T^T一直感觉是n^3,看了题解看来是数据水了么。。


#pragma comment(linker, "/STACK:1024000000,1024000000")  
#include <cstdio>
#include <string.h>
#define ll long long
#define inf 1e8
inline int min(int a, int b){return a<b?a:b;}
inline void rdl(ll &n){    
    n = 0;
    char c = getchar();    
    while(c < '0' || c > '9') c = getchar();    
    while(c >= '0' && c <= '9') n *= 10, n += (c - '0'),c = getchar();    
}    
inline void rd(int &n){    
    n = 0;
    char c = getchar();    
    while(c < '0' || c > '9') c = getchar();    
    while(c >= '0' && c <= '9') n *= 10, n += (c - '0'),c = getchar();    
}   
#define N 5005
int dp[N][N], cost[N];
ll sum[N], a[N];
int n;
int dfs(int l, int r){
    if(dp[l][r] != -1)return dp[l][r];
    if(l < 1 || r > n)return dp[l][r] = inf;
    if(sum[l] != sum[n] - sum[r-1])return inf;
    int s = l, t = r;
    int ans = inf;
    while(1 <= s && t <= n) {
        if(sum[l] - sum[s-1] == sum[t] - sum[r-1])
        {
            int tmp = cost[l-s+1] + cost[t-r+1];
            tmp += dfs(s-1, t+1);
            ans = min(ans, tmp);
            if(s>=2)s--;
            else t++;
        }
        else if(sum[l] - sum[s-1] > sum[t] - sum[r-1])
            t++;
        else if(sum[l] - sum[s-1] < sum[t] - sum[r-1])
            s--;
    }

    return dp[l][r] = ans;
}

int main(){
    int i, j, T, k;
    while(scanf("%d",&n), n){
        sum[0] = sum[n+1] = 0;
        for(i = 1; i <= n; i++)rdl(a[i]), sum[i] = sum[i-1] + a[i];
        for(i = 1; i <= n; i++)rd(cost[i]);
        memset(dp, -1, sizeof dp);
        dp[0][n+1] = 0;
        int ans = cost[n];
        for(i = 1; i < n; i++)
            ans = min(ans, dfs(i,i+1));
        for(i = 2; i < n; i++)
            ans = min(ans, dfs(i-1,i+1));
        int s = 1, t = n;
        while( s < t){
            if(sum[s] == sum[n] - sum[t-1])
            {
                ans = min(ans, dfs(s,t) + cost[t-s-1]);
                s++;
            }
            else if(sum[s] < sum[n] - sum[t-1])
                s++;
            else
                t--;
        }
        printf("%d\n", ans);
    }
    return 0;
}
/*
5
27 9 9 9 27
0 1000 1000 1 1000

5
27 9 8 10 27
0 1000 1000 1 1000

5
27 9 8 10 27
0 1000 1 1000 1000


*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值