1. 程式人生 > >BZOJ:1609: [Usaco2008 Feb]Eating Together麻煩的聚餐

BZOJ:1609: [Usaco2008 Feb]Eating Together麻煩的聚餐

space min inpu output 麻煩 i+1 src 魯棒性 ges

Description

為了避免餐廳過分擁擠,FJ要求奶牛們分3批就餐。每天晚飯前,奶牛們都會在餐廳前排隊入內,按FJ的設想所有第3批就餐的奶牛排在隊尾,隊伍的前端由設定為第1批就餐的奶牛占據,中間的位置就歸第2批就餐的奶牛了。由於奶牛們不理解FJ的安排,晚飯前的排隊成了一個大麻煩。 第i頭奶牛有一張標明她用餐批次D_i(1 <= D_i <= 3)的卡片。雖然所有N(1 <= N <= 30,000)頭奶牛排成了很整齊的隊伍但誰都看得出來,卡片上的號碼是完全雜亂無章的。 在若幹次混亂的重新排隊後,FJ找到了一種簡單些的方法:奶牛們不動,他沿著隊伍從頭到尾走一遍把那些他認為排錯隊的奶牛卡片上的編號改掉,最終得到一個他想要的每個組中的奶牛都站在一起的隊列,例如111222333或者333222111。哦,你也發現了,FJ不反對一條前後顛倒的隊列,那樣他可以讓所有奶牛向後轉,然後按正常順序進入餐廳。 你也曉得,FJ是個很懶的人。他想知道,如果他想達到目的,那麽他最少得改多少頭奶牛卡片上的編號。所有奶牛在FJ改卡片編號的時候,都不會挪位置。

Input

第1行: 1個整數:N 第2..N+1行: 第i+1行是1個整數,為第i頭奶牛的用餐批次D_i

Output

第1行: 輸出1個整數,為FJ最少要改幾頭奶牛卡片上的編號,才能讓編號變成他設想中的樣子

Sample Input

5
1
3
2
1
1
輸入說明:

隊列中共有5頭奶牛,第1頭以及最後2頭奶牛被設定為第一批用餐,第2頭奶牛的預設是第三批用餐,第3頭則為第二批用餐。

Sample Output

1

輸出說明:

如果FJ想把當前隊列改成一個不下降序列,他至少要改2頭奶牛的編號,一種可行的方案是:把隊伍中2頭編號不是1的奶牛的編號都改成1。不過,如果FJ選擇把第1頭奶牛的編號改成3就能把奶牛們的隊伍改造成一個合法的不上升序列了。
這東西……就是個DP 用dp[i][j]表示前i個數最後一個數為j時的最少更改次數,升降各做一遍,然後隨手還可以滾動一下,把空間壓到O(1)。 SXt的代碼魯棒性一點都不好……技術分享

(用的雲神的號)

#include<cstdio>
#include<algorithm>
using namespace std;

const int INF=100000000;
int n,m,dp[2][3],dq[2][3];
int main(){
 scanf("%d",&n);
 
for (int i=1;i<=n;i++){ scanf("%d",&m); m--; for (int j=m;j<3;j++) dp[0][m]=min(dp[1][j],dp[0][m]); for (int j=0;j<3;j++) if (j!=m){ dp[0][j]=dp[1][j]+1; for (int k=j+1;k<3;k++) dp[0][j]=min(dp[0][j],dp[1][k]+1); } for (int j=0;j<3;j++) dp[1][j]=dp[0][j],dp[0][j]=INF; for (int j=0;j<=m;j++) dq[0][m]=min(dq[1][j],dq[0][m]); for (int j=0;j<3;j++) if (j!=m){ dq[0][j]=dq[1][j]+1; for (int k=0;k<j;k++) dq[0][j]=min(dq[0][j],dq[1][k]+1); } for (int j=0;j<3;j++) dq[1][j]=dq[0][j],dq[0][j]=INF; } printf("%d\n",min(min(dp[1][0],min(dp[1][1],dp[1][2])),min(dq[1][0],min(dq[1][1],dq[1][2])))); }

BZOJ:1609: [Usaco2008 Feb]Eating Together麻煩的聚餐