1. 程式人生 > >[BZOJ1032][JSOI2007]祖碼Zuma 區間dp

[BZOJ1032][JSOI2007]祖碼Zuma 區間dp

clu 不同 pla ble inpu 選擇 logs href 成了

1032: [JSOI2007]祖碼Zuma

Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1105 Solved: 576 [Submit][Status][Discuss]

Description

這是一個流行在Jsoi的遊戲,名稱為祖瑪。精致細膩的背景,外加神秘的印加音樂襯托,仿佛置身在古老的國度裏面,進行一個神秘的遊戲——這就是著名的祖瑪遊戲。祖瑪遊戲的主角是一只石青蛙,石青蛙會吐出各種顏色的珠子,珠子造型美麗,並且有著神秘的色彩,環繞著石青蛙的是載著珠子的軌道,各種顏色的珠子會沿著軌道往前滑動,石青蛙必需遏止珠子們滾進去軌道終點的洞裏頭,如何減少珠子呢?就得要靠石青蛙吐出的珠子與軌道上的珠子相結合,顏色相同者即可以消失得分!直到軌道上的珠子通通都被清幹凈為止。 或許你並不了解祖瑪遊戲。沒關系。這裏我們介紹一個簡單版本的祖瑪遊戲規則。一條通道中有一些玻璃珠,每個珠子有各自的顏色,如圖1所示。玩家可以做的是選擇一種顏色的珠子(註意:顏色可以任選,這與真實遊戲是不同的)射入某個位置。

技術分享

圖1

圖2中玩家選擇一顆藍色珠子,射入圖示的位置,於是得到一個圖3的局面。

技術分享

圖2

技術分享

圖3 當玩家射入一顆珠子後,如果射入的珠子與其他珠子組成了三顆以上連續相同顏色的珠子,這些珠子就會消失。例如,將一顆白色珠子射入圖4中的位置,就會產生三顆顏色相同的白色珠子。這三顆珠子就會消失,於是得到圖5的局面。

技術分享

圖4

技術分享

圖5 需要註意的一點是,圖4中的三顆連續的黃色珠子不會消失,因為並沒有珠子射入其中。珠子的消失還會產生連鎖反應。當一串連續相同顏色的珠子消失後,如果消失位置左右的珠子顏色相同,並且長度大於2,則可以繼續消失。例如,圖6中,射入一顆紅色珠子後,產生了三顆連續的紅色珠子。當紅色珠子消失後,它左右都是白色的珠子,並且一共有四顆,於是白色珠子也消失了。之後,消失位置的左右都是藍色珠子,共有三顆,於是藍色珠子也消失。最終得到圖7的狀態。註意,圖7中的三顆黃色珠子不會消失,因為藍色珠子消失的位置一邊是紫色珠子,另一邊是黃色珠子,顏色不同。

技術分享

圖6

技術分享

圖7 除了上述的情況,沒有其他的方法可以消去珠子。現在,我們有一排珠子,需要你去消除。對於每一輪,你可以自由選擇不同顏色的珠子,射入任意的位置。你的任務是射出最少的珠子,將全部珠子消去。

Input

第一行一個整數n(n ≤ 500),表示珠子的個數第二行n個整數(32位整數範圍內),用空格分割,每個整數表示一種顏色的珠子。

Output

一個整數,表示最少需要射出的珠子個數。

Sample Input

9
1 1 2 2 3 3 2 1 1

Sample Output

1 設f[i][j]表示從i到j的最小方案,先將相同的顏色縮點,轉移顯然。 技術分享
 1 #include<iostream>
 2
#include<cstring> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 int n; 9 int a[505]; 10 int f[505][505]; 11 int cnt[505]; 12 int sum; 13 int main() { 14 scanf("%d",&n); 15 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 16 a[0]=-10; 17 for(int i=1;i<=n;i++) { 18 if(a[i]==a[i-1]) { 19 cnt[sum]++; 20 } 21 else { 22 a[++sum]=a[i]; 23 cnt[sum]=1; 24 } 25 } 26 memset(f,97,sizeof(f)); 27 for(int i=1;i<=sum;i++) if(cnt[i]>1) f[i][i]=1;else f[i][i]=2; 28 for(int len=2;len<=sum;len++) { 29 for(int i=1;i+len-1<=sum;i++) { 30 int j=i+len-1; 31 for(int k=i;k<j;k++) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]); 32 if(a[i]==a[j]) { 33 if(i+1==j) f[i][j]=1; 34 else if(cnt[i]>1||cnt[j]>1) f[i][j]=min(f[i][j],f[i+1][j-1]); 35 else f[i][j]=min(f[i][j],f[i+1][j-1]+1); 36 } 37 } 38 } 39 printf("%d",f[1][sum]); 40 }
View Code

[BZOJ1032][JSOI2007]祖碼Zuma 區間dp