1. 程式人生 > 其它 >UVA10559&P2135 方塊消除 題解

UVA10559&P2135 方塊消除 題解

消除方塊 傳送門
看了看題解區好像沒有這樣的解法?
這是一種比較懶癌的解法。(也比較詳細

首先來說說看狀態, \(f_{i,j,k}\)表示\([i, j]\)範圍消除完之後,剩餘k個顏色為\(color_{i}\)的最大分數
比如\(f_{i,j,0}\)表示把\([i, j]\)完全消除(啥都不剩)的最大分數

那麼問題來了我們為什麼要怎麼設呢?
想想看對於每一個塊我們只有兩種操作,
一種單獨消掉
一種是和其他塊組合起來消掉:比如12221, 我們可以把222消掉,然後讓11組合起來
對,也就是說,當我們要把兩個塊組合起來時, 一定要把他們之間的所有塊先消除, 例如把i, k組合起來,要先把\([i+1, k-1]\)

這個區間消除掉, 得到分數是\(f_{l+1, k-1, 0}\)
當我們計算\(f_{i, j, k}\)時, 假設i是新放進去的塊([i+1, j]已經計算好了)
直接消掉i顯然為\(1+f_{i+1, j, 0}\), 進一步考慮組合
我們列舉\([i+1, j]中每一個為color_{i}的塊k\)
我們考慮在\([k, j]\)中選擇若干個塊與i合併 分數為\(f_{k,j,x}\)(剩餘x個用來合併) \([i+1, k-1]\)直接消掉\(f_{i+1, k-1, 0}\)
列舉這個x,ok
(這個地方需要仔細思考)

複雜度\(O(n^4)\)

實在不行看看程式碼

	for(int i=1; i<=n; i++){
		f[i][i][1] = 0;//直接把這個塊保留,不需要消除,所以分數為0 
		f[i][i][0] = 1;//直接消除這一個塊, 分數1 
	}
	for(int j=2; j<=n; j++){
		for(int i=1; i+j-1<=n; i++){
			int l=i, r=i+j-1;
			f[l][r][0] = f[l+1][r][0] + 1;//直接消除i 
			f[l][r][1] = f[l+1][r][0];//直接保留i 

			for(int st=l+1; st<=r; st++){
				if(color[st] != color[l]) continue;//列舉上面的“x” 
				for(int k=1; k<n; k++){//注意邊界 
					f[l][r][k+1] = max(f[l][r][k+1], f[l+1][st-1][0] + f[st][r][k]);
					//從st-r中取k個與i合併, 一共k+1個 
					f[l][r][0] = max(f[l][r][0], f[l][r][k+1] + (k+1)*(k+1));
					//考慮把k+1個直接消除, 更新最大分數 
				} 
			}
		}
	}