1. 程式人生 > >UVA10559 Blocks(區間dp)

UVA10559 Blocks(區間dp)

else sizeof 顏色 cin name scanf cout strong string

有n個帶有顏色的方塊,沒消除一段長度為x的連續的相同顏色的方塊可以得到x^2的分數,讓你用一種最優的順序消除所有方塊使得得分最多。

輸入格式 第一行包含測試的次數t(1≤t≤15) 每個案例包含兩行。第一行包含整數n(1≤n≤200),即框數。第二行包含n個數,代表每個盒子的顏色。數字的大小1~n內。

Solution

n比較小,所以我們要用n^3的dp。

我們設dp[i][j][k]表示從i縮到j,j要和j後面的k個格子縮到一起能獲得的最大分數。

轉移的話枚舉斷點,如果有一個點和j相等,就把k向前傳遞,否側向後傳遞。

Code

#include<iostream>
#include
<cstdio> #include<cstring> using namespace std; int x,dp[309][309][309],a[309],b[309],n,tot,t,p; int dfs(int i,int j,int s){ if(dp[i][j][s])return dp[i][j][s]; if(i>j)return 0; if(i==j)return dp[i][j][s]=(b[j]+s)*(b[j]+s); for(int k=i;k<j;++k) if(a[k]==a[j]) dp[i][j][s]
=max(dp[i][j][s],dfs(i,k,s+b[j])+dfs(k+1,j-1,0)); else dp[i][j][s]=max(dp[i][j][s],dfs(i,k,0)+dfs(k+1,j,s)); return dp[i][j][s]; } int main(){ cin>>t; while(t--){ p++; cin>>n;a[0]=-99;tot=0; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;++i){ scanf("%d",&x);
if(x==a[tot])b[tot]++; else a[++tot]=x,b[tot]=1; } cout<<"Case "<<p<<": "<<dfs(1,tot,0)<<endl; } return 0; }

UVA10559 Blocks(區間dp)