POJ 1390

题意:给定n个不同颜色的盒子,连续的相同颜色的k个盒子可以拿走,权值为k*k,求把所有盒子拿完的最大权值。

题解:记忆化搜索,dp[ll][rr][kk]代表在区间[ll,rr]取盒子,其中ll前面有k个盒子颜色和rr一样,可以重叠在rr上消去。

   那么,dp[ll][rr][kk]=max(dp[ll][i][kk+len[rr]]+dp[i+1,rr-1][0],dp[ll][rr-1][0]+pow(len[rr]+kk)),i是所有位于[ll,rr-1]区间且与rr颜色相同的盒子;

View Code
 1 #include<cstdio>

 2 #include<cstring>

 3 #include<algorithm>

 4 using namespace std;

 5 int dp[205][205][205];

 6 int col[205],len[205];

 7 inline int pow(int x)

 8 {

 9     return x*x;

10 }

11 int dfs(int ll,int rr,int kk)

12 {

13     if(ll>rr)

14         return 0;

15     else if(dp[ll][rr][kk])

16         return dp[ll][rr][kk];

17     else if(ll==rr)

18         return dp[ll][rr][kk]=pow(kk+len[rr]);

19     else

20     {

21         int ans=dfs(ll,rr-1,0)+pow(len[rr]+kk);

22         for(int i=rr-1;i>=ll;i--)

23             if(col[i]==col[rr])

24                 ans=max(ans,dfs(ll,i,kk+len[rr])+dfs(i+1,rr-1,0));

25         return dp[ll][rr][kk]=ans;

26     }

27 }

28 int main()

29 {

30     int T,ca=0;

31     for(scanf("%d",&T);T;T--)

32     {

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

34         int n,num=0,c;

35         scanf("%d",&n);

36         scanf("%d",&col[0]);

37         len[0]=1;

38         for(int i=1;i<n;i++)

39         {

40             scanf("%d",&c);

41             if(col[num]==c)

42                 len[num]++;

43             else

44                 col[++num]=c,len[num]=1;

45         }

46         printf("Case %d: %d\n",++ca,dfs(0,num,0));

47     }

48     return 0;

49 }

你可能感兴趣的:(poj)