区间dp LightOj 1422 Halloween Costumes

题目链接:

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27130

题意:

一个人赶几场舞会,每场舞会穿的衣服不一样。规定衣服可脱,重新穿时算新的一件。因为可以几件衣服套在一起,问最少用几件新衣服。

思路:

在解释中理清思路。dp[i][j]为第i到第j场需要穿的最少衣服数目。对于每个dp,初始化为dp[i][j] = 1 +dp[i+1][j],然后在i+1到j的区间里找最优值k。若data[k] == data[i],则dp = gmin(dp[i+1][k-1]+dp[k][j]),否则dp[i][j] = gmin(dp[i+1][k-1]+dp[k][j]+1)。(即考虑假设k场与i场的衣服相同,则假设i场衣服不脱,一直穿到k场,并且由于动态规划已经得到最优解的缘故,dp[i+1][k-1]已经得到最优值)。原本思考的时候想到变换以哪件衣服为底时会发生翻转问题,看完题解发现是不需要换底的。指需要加底,即假设一开始就存在哪些衣服、它们的顺序就好。

源码:

#include <bits/stdc++.h>

#define gmin(a,b) a<b?a:b

const int MAXN = 100+5;

int dp[MAXN][MAXN];

int data[MAXN];

int main()

{

   int t;

   scanf("%d",&t);

   for(int i=1; i<=t; i++){

       int n;

       scanf("%d",&n);

       for(int i=0; i<n; i++){

           scanf("%d",&data[i]);

       }

       memset(dp,0,sizeof(dp));

       for(int i=0; i<n; i++)

           dp[i][i] = 1;

       for(int i=1; i<=n; i++){///length

           for(int j=n-1; j>=0; j--){///start point

                int st = j-i;

                if(st < 0)

                    break;

                dp[st][j] = 1 + dp[st+1][j];

                for(int k = st+1; k<=j;k++){

                    if(data[k] == data[st]){

                        dp[st][j] =gmin(dp[st][j], dp[st+1][k-1] + dp[k][j]);

                    }

                }

           }

       }

//       for(int i=0; i<n; i++){

//            for(int j=0; j<n; j++)

//                printf("%d",dp[i][j]);

//            printf("\n");

//       }

       printf("Case %d: %d\n",i,dp[0][n-1]);

    }

   return 0;

}

你可能感兴趣的:(区间dp LightOj 1422 Halloween Costumes)