zoukankan      html  css  js  c++  java
  • lightoj 1422 Halloween Costumes 区间DP

    的确挺神奇的一道题,跟lyc讨论了一会才想清楚正确性。

    用dp[x][y]表示完成[x,y]这些舞会至少需要多少衣服。注意这里dp的定义很明确,就是只完成[x,y],之前不需要穿衣服,之后也不需要穿衣服。

    那么对应的,答案应该就是dp[1][n]。

    我们考虑转移,这道题中,唯一能优化的地方,无非就是我穿了一件衣服,我没脱,过一会又用上了。

    那么如果c[x] == c[y]的话,dp[x][y] == dp[x][y - 1],因为最后一件衣服c[y]没用得着重新穿,直接用的c[x]。这里面x,y都是边界,最里面一直藏个衣服显然不影响我中间怎么倒腾。

    除了这个情况以外,还有两个情况,一个是我把c[x]脱了,那么dp[x][y] = dp[x][x] + dp[x + 1][y]了。还有一个情况就是我把c[x]留着,等到[x,y]中的某个k正好露出来,用完再脱掉。

    两个情况可以用一个for循环统一起来。

    这道题,感觉最大的一个体会还是,要搞清楚DP的定义,我只考虑[x,y]部分,那就不去管外面有没有影响,只要每一层的转移和考虑都是周全的,那就没有问题。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int inf = 10000000;
    int dp[110][110],T,n,cnt,c[110];
    int dfs(int l,int r)
    {
        if (dp[l][r] != -1)
            return dp[l][r];
        int minn = inf;
        if (c[l] == c[r])
            minn = min(minn,dfs(l,r - 1));
        for (int k = l;k <= r - 1;k++)
            if (c[l] == c[k])
                minn = min(minn,dfs(l,k) + dfs(k + 1,r));
        return dp[l][r] = minn;
    }
    int main()
    {
        for (scanf("%d",&T);T;T--)
        {
            memset(dp,-1,sizeof(dp));
            scanf("%d",&n);
            for (int i = 1;i <= n;i++)
                dp[i][i] = 1;
            for (int i = 1;i <= n;i++)
                scanf("%d",&c[i]);
            printf("Case %d: %d
    ",++cnt,dfs(1,n));
        }
        return 0;
    }
    心之所动 且就随缘去吧
  • 相关阅读:
    高性能Javascript 选择器API学习笔记
    Backbone学习笔记二 Events
    递归用函数、存储过程实现的效果
    用触发器实现动态新增列
    局域网自动备份删除
    游标变量用法经典
    如何区分大小写字母、全角半角
    列的分拆显示
    2005的行列转换
    批量分离和附加数据库
  • 原文地址:https://www.cnblogs.com/iat14/p/12008357.html
Copyright © 2011-2022 走看看