P2135 方塊消除
阿新 • • 發佈:2021-10-27
目錄
P2135 方塊消除
題目
https://www.luogu.com.cn/problem/UVA10559
https://www.luogu.com.cn/problem/P2135
題目描述
Jimmy最近迷上了一款叫做方塊消除的遊戲。遊戲規則如下:n個帶顏色方格排成一列,相同顏色的方塊連成一個區域(如果兩個相鄰方塊顏色相同,則這兩個方塊屬於同一區域)。為簡化題目,將連起來的同一顏色方塊的數目用一個數表示。
例如,9 122233331表示為
4 1 2 3 1
1 3 4 1
遊戲時,你可以任選一個區域消去。設這個區域包含的方塊數為x,則將得到x^2個分值。方塊消去之後,其餘的方塊就會豎直落到底部或其他方塊上。而且當有一列方塊被完全消去時,其右邊的所有方塊就會向左移一格。Jimmy希望你能找出得最高分的最佳方案,你能幫助他嗎?
輸入格式
第一行包含一個整數m(1<=m<=50),表示同顏色方塊區域的數目。第二行包含m個數,表示每個方塊的顏色(1到m之間的整數)。
輸出格式
僅一個整數,即最高可能得分。
輸入輸出樣例
輸入 #1
4 1 2 3 1 1 3 4 1
輸出 #1
29
思路
設\(f_{i,j,k}\)表示消除\(l,r\)之間的方塊,其中顏色和\(i\)相同的方塊保留了\(k\)個時的最大得分.
對於初始化,顯然有:\(f_{i,i,0}=num_i^2,f_{i,i,num_i}=0\).其中\(num_i\)為第\(i\)個區域內方塊的數量.
轉移稍顯複雜,具體可以看程式碼,核心就是列舉保留還是消去.
程式碼
#include <iostream> #include <cstdio> #include <cstring> #define int long long using namespace std; int read() { int re = 0; char c = getchar(); bool negt = false; while(c < '0' || c > '9') negt |= (c == '-') , c = getchar(); while(c >= '0' && c <= '9') re = (re << 1) + (re << 3) + c - '0' , c = getchar(); return negt ? -re : re; } const int N = 210; int col[N];//color int num[N]; int f[55][55][1010]; int n; int solve() { memset(col , 0 , sizeof(col)); memset(num , 0 , sizeof(num)); memset(f , 0 , sizeof(f)); n = read(); int sum = 0; for(int i = 1 ; i <= n ; i++)col[i] = read(); for(int i = 1 ; i <= n ; i++)num[i] = read() , sum += num[i]; memset(f , -0x3f , sizeof(f)); for(int i = 1 ; i <= n ; i++) f[i][i][0] = num[i] * num[i] , f[i][i][num[i]] = 0; for(int i = n ; i > 0 ; i--) for(int j = i + 1 ; j <= n ; j++) { for(int k = i ; k < j ; k++) { f[i][j][0] = max(f[i][j][0] , f[i][k][0] + f[k + 1][j][0]); if(col[i] == col[k + 1]) for(int l = 0 ; l <= sum ; l++) {//列舉[k+1,j]段留下l個顏色相同為col[i]的方塊 f[i][j][l] = max(f[i][j][l] , f[i][k][0] + f[k + 1][j][l]); if(i + 1 <= k) { f[i][j][0] = max( f[i][j][0] , f[i + 1][k][0] + f[k + 1][j][l] + (l + num[i]) * (l + num[i]) ) ; f[i][j][l + num[i]] = max( f[i][j][l + num[i]] , f[i + 1][k][0] + f[k + 1][j][l] ); } } } } return f[1][n][0]; } signed main() { printf("%lld" , solve()); return 0; }