poj1390區間dp+記憶化搜尋
阿新 • • 發佈:2019-02-19
題目大意:一排方塊有顏色,每次只能消去相同顏色的塊,分值為每次消去數量的平方,求最大和。
思路:區間dp,dp[i][j][k]表示從i到j塊且j後面有k塊與j不想領但同顏色。
則j可以和後面的合併也可以和前面的合併。具體看程式碼
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <fstream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <vector> #include <map> #include <set> #include <iomanip> using namespace std; //#pragma comment(linker, "/STACK:102400000,102400000") #define maxn 210 #define MOD 1000000007 #define mem(a , b) memset(a , b , sizeof(a)) #define LL long long #define INF 100000000 int n ; int dp[maxn][maxn][maxn]; int arr[maxn]; int solve(int l , int r , int k) { if(l > r ) return 0; if(dp[l][r][k]) return dp[l][r][k]; dp[l][r][k] = solve(l , r-1 , 0) + (1+k) * (1+k); for(int i = r-1 ; i >= l ; i--) { if(arr[r] == arr[i]) { dp[l][r][k] = max(dp[l][r][k] , solve(l , i , k + 1) + solve(i + 1 , r - 1, 0)); } } return dp[l][r][k]; } int main() { int t ; int ncase = 1; scanf("%d" , &t); while(t--) { scanf("%d" , &n); for(int i = 1 ; i <= n ; i ++) scanf("%d" , &arr[i]); memset(dp , 0 , sizeof(dp)); printf("Case %d: %d\n" , ncase ++ , solve(1 , n , 0)); } return 0; }