1. 程式人生 > >UVA - 10559 Blocks

UVA - 10559 Blocks

print block == max cas eof cstring blog i+1

題文:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1500(或者見紫書)

題解:

  因為這個題目我們用區間的dp常見套路設dp[i][j]表示處理到i~j的最大貢獻不能靠枚舉斷點進行轉移,所以我們要更細致的描述這個狀態。設dp[i][j][k],表示把第i個區間和第j個區間合並,並且由於前面的消除有k個與區間j的顏色相同的方塊接著j後面的最大貢獻。

  那麽轉移我們可以考慮1.直接將j區間和k消除。dp[i][j][k]=dp[i][j-1][0]+(len[j]+k)^2。2.考慮將j和前面的某個顏色相同的區間合並,所以要消除中間的某幾段區間。

既:dp[l][r][k]=dp[i+1,][r-1][0]+dp[l][i][k+len[r]]。的確這個題目還是自己好好消化吧,是道經典的dp題目。

代碼:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<cstring>
using namespace std;
int color[1000],len[1000],n,t;
int shu[1000],dp[300][300][300];

void cl(){
    memset(color,
0,sizeof(color)); memset(len,0,sizeof(len)); memset(shu,0,sizeof(shu)); memset(dp,0,sizeof(dp)); } int dfs(int l,int r,int k){ if(l>r) return 0; if(l==r) return (len[l]+k)*(len[l]+k); if(dp[l][r][k]!=0) return dp[l][r][k]; dp[l][r][k]=dfs(l,r-1,0)+(len[r]+k)*(len[r]+k);
for(int i=l;i<r;i++){ if(color[i]==color[r]) dp[l][r][k]=max(dp[l][r][k],dfs(i+1,r-1,0)+dfs(l,i,k+len[r])); } return dp[l][r][k]; } int main(){ scanf("%d",&t); for(int hh=1;hh<=t;hh++){ scanf("%d",&n); cl(); for(int i=1;i<=n;i++) scanf("%d",&shu[i]); int star=1,now=1,num=0,lenn=0; while(now<=n){ while(shu[star]==shu[now]){ now++,lenn++; } color[++num]=shu[star]; len[num]=lenn; lenn=0;star=now; } printf("Case %d: %d\n",hh,dfs(1,num,0)); } }

UVA - 10559 Blocks