1. 程式人生 > >Bzoj1032 [JSOI2007]祖碼Zuma

Bzoj1032 [JSOI2007]祖碼Zuma

name 技術 set 其中 main ace %d ons input

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1003 Solved: 512

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

HINT

據說此題標程有誤,致使數據全錯....

Source

動態規劃 區間DP

我們把連續的顏色相同的珠子都預先合並到一個位置,記錄一下數量。

接下來顯然是個區間DP,最裸的那種。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 using namespace std;
 7 const int mxn=605;
 8 int read(){
 9     int x=0,f=1;char ch=getchar();
10     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();}
11     while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();}
12     return x*f;
13 }
14 int n;
15 int a[mxn],c[mxn],cnt=0;
16 int f[mxn][mxn];
17 void solve(){
18     int i,j,k;
19     memset(f,0x3f,sizeof f);
20     for(int i=1;i<=n;i++)
21         f[i][i]=(c[i]>=2)?1:(3-c[i]);
22     for(int len=2;len<=n;len++){
23         for(int i=1;i<=n;i++){
24             j=i+len-1;if(j>n)break;
25             for(int k=i;k<j;k++)
26                 f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
27             if(a[i]==a[j]){
28                 f[i][j]=min(f[i][j],f[i+1][j-1]+(c[i]+c[j]<3));
29             }
30         }
31     }
32     printf("%d\n",f[1][n]);
33     return;
34 }
35 int main(){
36     int i,j,x;
37     n=read();
38     for(i=1;i<=n;i++){
39         x=read()+1;
40         if(x==a[cnt])c[cnt]++;
41         else{
42             a[++cnt]=x;
43             c[cnt]=1;
44         }
45     }
46     n=cnt;
47     solve();
48     return 0;
49 }

Bzoj1032 [JSOI2007]祖碼Zuma