区间dp入门[POJ2955][HDU2476][POJ3186][POJ1651][HDU4632][HDU4283][HDU4570][POJ3280]

区间dp问题,通常给出一个序列,用dp[ i ][ j ] 表示序列为ai,a(i + 1)...aj时的答案,而较长的序列的答案由较短的序列的答案递推得到,让人想到矩阵连乘顺序问题。

所以解题的时候会用到3个循环:

第一层枚举序列长度 jj

第二层枚举序列开头的位置 i

第三层枚举序列 [i, i + jj ] 中间点 k,其中第三层有时是不需要的


下面是一些区间dp入门题,大同小异,这里就不给出思路了,看下代码大概就明白了


题目:POJ 2955 http://poj.org/problem?id=2955

代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define MOD 1000000007
#define INF 0x7fffffff
using namespace std;
int dp[105][105];
char s[105];

int match(int l, int r)
{
    if(s[l] == '(' && s[r] == ')') return 1;
    if(s[l] == '[' && s[r] == ']') return 1;
    return 0;
}

int main()
{
    #ifdef LOCAL
    freopen("dpdata.txt", "r", stdin);
    #endif

    while(scanf("%s", s) != EOF && s[0] != 'e')
    {
        int len = strlen(s);
        memset(dp, 0, sizeof(dp));
        for(int jj = 1; jj < len; jj++)
        {
            for(int i = 0; i + jj < len; i++)
            {
                int j = i + jj;
                if(match(i, j))
                {
                    dp[i][j] = max(dp[i][j], dp[i + 1][j - 1] + 2);
                }
                for(int k = i; k < j; k++)
                {
                    dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j]);
                }
                //printf("dp[%d][%d]=%d\n", i, j, dp[i][j]);
            }
        }
        printf("%d\n", dp[0][len - 1]);
    }

    return 0;
}



题目:HDU 2476  http://acm.hdu.edu.cn/showproblem.php?pid=2476

代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define MOD 1000000007
#define INF 0x7fffffff
using namespace std;
char A[105], B[105];
int dp[105][105], ans[105];

int main()
{
    #ifdef LOCAL
    freopen("dpdata.txt", "r", stdin);
    #endif

    int l, r;
    while(scanf("%s%s", A, B) != EOF)
    {
        int len = strlen(A);
        memset(dp, 0, sizeof(dp));
        for(int jj = 0; jj < len; jj++)
        {
            for(int i = 0; i + jj < len; i++)
            {
                int j = i + jj;
                dp[i][j] = dp[i + 1][j] + 1;
                for(int k = i + 1; k <= j; k++)
                {
                    if(B[i] == B[k])
                    dp[i][j] = min(dp[i][j], dp[i + 1][k] + dp[k + 1][j]);
                }
                //printf("dp[%d][%d]=%d\n", i, j, dp[i][j]);
            }
        }
        for(int i = 0; i < len; i++)
            ans[i] = dp[0][i];
        for(int i = 0; i < len; i++)
        {
            if(B[i] == A[i])
            {
                if(i == 0)
                    ans[i] = 0;
                else
                    ans[i] = ans[i - 1];
            }
            else
            {
                for(int j = 0; j < i; j++)
                {
                    ans[i] = min(ans[i], ans[j] + dp[j + 1][i]);
                }
            }
        }
        printf("%d\n", ans[len - 1]);
    }

    return 0;
}

题目:POJ 3186  http://poj.org/problem?id=3186

代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define MOD 1000000007
#define INF 0x7fffffff
using namespace std;
int v[2005], sum[2005], dp[2005][2005], a[2005][2005];

int main()
{
    #ifdef LOCAL
    freopen("dpdata.txt", "r", stdin);
    #endif

    int n;
    while(scanf("%d", &n) != EOF)
    {
        memset(dp, 0, sizeof(dp));
        memset(a, 0, sizeof(a));
        for(int i = 0; i < n; i++)
        {
            scanf("%d", &v[i]);
            dp[i][i] = v[i];
            a[i][i] = v[i];
            //printf("a[%d][%d]=%d\n", i, i, a[i][i]);
        }
        sum[0] = v[0];
        for(int i = 1; i < n; i++)
        {
            sum[i] = sum[i - 1] + v[i];
            a[0][i] = sum[i];
            //printf("a[0][%d]=%d\n", i, a[0][i]);
        }
        for(int i = 1; i < n; i++)
        {
            for(int j = i + 1; j < n; j++)
            {
                a[i][j] = sum[j] - sum[i - 1];
                //printf("a[%d][%d]=%d\n", i, j, a[i][j]);
            }
        }
        for(int jj = 1; jj < n; jj++)
        {
            for(int i = 0; i + jj < n; i++)
            {
                int j = i + jj;
                dp[i][j] = max(dp[i][j], dp[i + 1][j] + a[i + 1][j] + a[i][i]);
                dp[i][j] = max(dp[i][j], dp[i][j - 1] + a[i][j - 1] + a[j][j]);
                //printf("dp[%d][%d]=%d\n", i, j, dp[i][j]);
            }
        }
        printf("%d\n", dp[0][n -1]);
    }

    return 0;
}



题目:POJ 1651  http://poj.org/problem?id=1651

代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define MOD 1000000007
#define INF 0x7fffffff
using namespace std;
int dp[105][105];

int main()
{
    #ifdef LOCAL
    freopen("dpdata.txt", "r", stdin);
    #endif

    int n, a[105];
    while(scanf("%d", &n) != EOF)
    {
        for(int i = 0; i < n; i++)
        {
            scanf("%d", &a[i]);
        }
        for(int i = 0; i <= n; i++)
        {
            for(int j = 0; j <= n; j++)
                dp[i][j] = 100000100;
        }
        for(int i = 1; i < n - 1; i++)
        {
            dp[i - 1][i + 1] = a[i - 1] * a[i] * a[i + 1];
            //printf("dp[%d][%d]=%d\n", i - 1, i + 1, dp[i - 1][i + 1]);
        }
        for(int jj = 3; jj < n; jj++)
        {
            for(int i = 0; i + jj < n; i++)
            {
                int j = i + jj;
                for(int k = i + 2; k + 1< j; k++)
                {
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]
                                       + a[i] * a[k] * a[j]);
                }
                dp[i][j] = min(dp[i][j], dp[i][j - 1] + a[i] * a[j - 1] * a[j]);
                dp[i][j] = min(dp[i][j], dp[i + 1][j] + a[i] * a[i + 1] * a[j]);
                //printf("dp[%d][%d]=%d\n", i, j, dp[i][j]);
            }
        }
        printf("%d\n", dp[0][n - 1]);
    }

    return 0;
}

题目:HDU 4632  http://acm.hdu.edu.cn/showproblem.php?pid=4632

代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define MOD 10007
#define INF 0x7fffffff
using namespace std;
char s[1005];
int dp[1005][1005];

int main()
{
    #ifdef LOCAL
    freopen("dpdata.txt", "r", stdin);
    #endif

    int t;
    scanf("%d", &t);
    for(int cas = 1; cas <= t; cas++)
    {
        scanf("%s", s);
        int len = strlen(s);
        memset(dp, 0, sizeof(dp));
        for(int i = 0; i < len; i++)
        {
            dp[i][i] = 1;
        }
        for(int jj = 1; jj < len; jj++)
        {
            for(int i = 0; i + jj < len; i++)
            {
                int j = i + jj;
                dp[i][j] = max(dp[i][j], dp[i][j - 1] + dp[i + 1][j]
                                   - dp[i + 1][j - 1] + MOD);
                if(s[i] == s[j])
                {
                    dp[i][j] += dp[i + 1][j - 1] + 1 + MOD;
                }
                dp[i][j] %= MOD;
            }
        }
        printf("Case %d: %d\n", cas, dp[0][len - 1]);
    }

    return 0;
}

题目:HDU 4283  http://acm.hdu.edu.cn/showproblem.php?pid=4283

代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define MOD 1000000007
#define INF 0x7fffffff
using namespace std;
int d[105], dp[105][105], a[105][105], sum[105];

int main()
{
    #ifdef LOCAL
    freopen("dpdata.txt", "r", stdin);
    #endif

    int t, n;
    scanf("%d", &t);
    for(int cas = 1; cas <= t; cas++)
    {
        scanf(" %d", &n);
        memset(dp, 0, sizeof(dp));
        memset(a, 0, sizeof(a));
        for(int i = 0; i < n; i++)
        {
            scanf("%d", &d[i]);
            dp[i][i] = 0;
            a[i][i] = d[i];
        }
        sum[0] = d[0];
        for(int i = 1; i < n; i++)
        {
            sum[i] = a[0][i] = sum[i - 1] + d[i];
        }
        for(int i = 0; i < n; i++)
        {
            for(int j = i + 1; j < n; j++)
            {
                dp[i][j] = 1000010;
                if(i > 0)a[i][j] = sum[j] - sum[i - 1];
                //printf("a[%d][%d]=%d\n", i, j, a[i][j]);
            }
        }
        for(int j = 1; j < n; j++)
        {
            for(int i = 0; i + j < n; i++)
            {
                //dp[i][i + j] = min(dp[i][i + j], dp[i + 1][i + j] + a[i + 1][i + j]);
                for(int k = 0; k <= j; k++)
                {
                    dp[i][i + j] = min(dp[i][i + j], dp[i + 1][i + k] + k * a[i][i]
                                       + dp[i + k + 1][i + j] + (k + 1) * a[i + k + 1][i + j]);
                }
                //dp[i][i + j] = min(dp[i][i + j], dp[i + 1][i + j] + a[i][i] * j);
                //printf("dp[%d][%d]=%d\n", i, i + j, dp[i][i + j]);
            }
        }
        printf("Case #%d: %d\n", cas, dp[0][n - 1]);
    }

    return 0;
}


题目:HDU 4570  http://acm.hdu.edu.cn/showproblem.php?pid=4570

代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define MOD 1000000007
#define INF 1 << 30 - 1
typedef long long ll;
using namespace std;
ll dp[70][70], a[70];

int main()
{
    #ifdef LOCAL
    freopen("dpdata.txt", "r", stdin);
    #endif

    int t, n;
    //printf("INF=%I64d\n", INF);
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        memset(dp, 0, sizeof(dp));
        for(int i = 0; i < n; i++)
        {
            scanf("%I64d", &a[i]);
        }
        for(int i = 0; i < n; i++)
        {
            dp[i][i] = a[i] * 2;
            for(int j = i + 1; j < n; j++)
            {
                dp[i][j] = INF;
            }
        }
        for(int jj = 1; jj < n; jj++)
        {
            for(int i = 0; i + jj < n; i++)
            {
                int j = i + jj;
                for(int k = i; k < j; k++)
                {
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]);
                    if(jj <= 19)
                    {
                        ll cur = a[i];
                        for(int cnt = 1; cnt <= (jj + 1); cnt++)
                            cur *= 2;
                        dp[i][j] = min(dp[i][j], cur);
                    }
                }
                //printf("dp[%d][%d]=%d\n", i, j, dp[i][j]);
            }
        }
        printf("%I64d\n", dp[0][n - 1]);
    }

    return 0;
}

题目:POJ 3280  http://poj.org/problem?id=3280
代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define MOD 1000000007
#define INF 0x7fffffff - 20010
using namespace std;
char s[2005];
int add[30], del[30], dp[2005][2005];

int main()
{
    #ifdef LOCAL
    freopen("dpdata.txt", "r", stdin);
    #endif

    int n, m;
    char c;
    while(scanf("%d %d ", &n, &m) != EOF)
    {
        memset(add, 0, sizeof(add));
        memset(del, 0, sizeof(del));
        memset(dp, 0, sizeof(dp));
        for(int i = 0; i <= m; i++)
        {
            for(int j = i + 1; j <= m; j++)
            {
                dp[i][j] = INF;
            }
        }
        scanf("%s", s);
        for(int i = 0; i < n; i++)
        {
            scanf(" %c", &c);
            scanf("%d%d", &add[c - 'a'], &del[c - 'a']);
        }
        for(int jj = 1; jj < m; jj++)
        {
            for(int i = 0; i + jj < m; i++)
            {
                int j = i + jj;
                if(s[i] != s[j])
                {
                    dp[i][j] = min(dp[i][j], dp[i + 1][j] + add[s[i] - 'a']);
                    dp[i][j] = min(dp[i][j], dp[i][j - 1] + add[s[j] - 'a']);
                    dp[i][j] = min(dp[i][j], dp[i + 1][j] + del[s[i] - 'a']);
                    dp[i][j] = min(dp[i][j], dp[i][j - 1] + del[s[j] - 'a']);
                }
                else
                {
                    dp[i][j] = min(dp[i][j], dp[i + 1][j - 1]);
                }
                //printf("dp[%d][%d] = %d\n", i, j, dp[i][j]);
            }
        }
        printf("%d\n", dp[0][m - 1]);
    }

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值