題目背景
Usaco Feb08 Bronze
題目描述
為了避免餐廳過分擁擠,FJ要求奶牛們分2批就餐。每天晚飯前,奶牛們都會在餐廳前排隊入內,按FJ的設想,所有第2批就餐的奶牛排在隊尾,隊伍的前半部分則由設定為第1批就餐的奶牛佔據。由於奶牛們不理解FJ的安排,晚飯前的排隊成了一個大麻煩。 第i頭奶牛有一張標明她用餐批次D_i(1 <= D_i <= 2)的卡片。雖然所有N頭奶牛排成了很整齊的隊伍,但誰都看得出來,卡片上的號碼是完全雜亂無章的。 在若干次混亂的重新排隊後,FJ找到了一種簡單些的方法:奶牛們不動,他沿著隊伍從頭到尾走一遍,把那些他認為排錯隊的奶牛卡片上的編號改掉,最終得到一個他想要的每個組中的奶牛都站在一起的佇列,例如112222或111122。有的時候,FJ會把整個佇列弄得只有1組奶牛(比方說,1111或222)。 你也曉得,FJ是個很懶的人。他想知道,如果他想達到目的,那麼他最少得改多少頭奶牛卡片上的編號。所有奶牛在FJ改卡片編號的時候,都不會挪位置。
輸入輸出格式
輸入格式:
第1行: 1個整數:N * 第2..N+1行: 第i+1行是1個整數,為第i頭奶牛的用餐批次D_i
輸出格式:
一行: 輸出1個整數,為FJ最少要改幾頭奶牛卡片上的編號,才能讓編號變成他設想中的樣子。
輸入輸出樣例
輸入樣例#1:
7 2 1 1 1 2 2 1
輸出樣例#1:
2
輸入樣例#2:
5 2 2 1 2 2
輸出樣例#2:
1
說明
1 <= N <= 30000
用dp[i][j]表示列舉到第i頭牛,將第i頭牛的狀態改為j+1所需要的最小方案數
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<queue> 6 using namespace std; 7 void read(int &n) 8 { 9 char c='+';int x=0;bool flag=0; 10 while(c<'0'||c>'9') 11 {c=getchar();if(c=='-')flag=1;} 12 while(c>='0'&&c<='9') 13 {x=x*10+(c-48);c=getchar();} 14 flag==1?n=-x:n=x; 15 } 16 int n; 17 int a[30001]; 18 int dp[30001][3]; 19 int main() 20 { 21 read(n); 22 for(int i=1;i<=n;i++) 23 read(a[i]); 24 if(a[1]==1) 25 { 26 dp[1][0]=0; 27 dp[1][1]=1;// 改成2 28 } 29 else 30 { 31 dp[1][1]=0; 32 dp[1][0]=1; 33 } 34 for(int i=2;i<=n;i++) 35 { 36 if(a[i]==1)// 當前是一 37 { 38 dp[i][0]=dp[i-1][0]; 39 dp[i][1]=min(dp[i-1][1],dp[i-1][0])+1; 40 // 需要改成2 41 } 42 else // 當前是2 43 { 44 dp[i][0]=dp[i-1][0]+1; 45 dp[i][1]=min(dp[i-1][1],dp[i-1][0]); 46 } 47 } 48 printf("%d",min(dp[n][0],dp[n][1])); 49 return 0; 50 }