USACO FEB08 Silver Eating Together 麻煩的聚餐
由於結果要分兩種情況(不下降序列和不上升序列),要進性兩遍動態規劃
狀態設定
* F[i,j]表示前i個數中,第i個數改爲j時,滿足不下降序列所需的一共最少更改次數。
* G[i,j]表示前i個數中,第i個數改爲j時,滿足不上升序列所需的一共最少更改次數。
狀態轉移方程
* F[i,j]=
o Min{ F[i-1,k] (1<=k<=j) } + 1 (當第i個數不爲j時,需要更改)
o Min{ F[i-1,k] (1<=k<=j) } (當第i個數爲j時,不需更改)
* G[i,j]=
o Min{ G[i-1,k] (j<=k<=3) } + 1 (當第i個數不爲j時,需要更改)
o Min{ G[i-1,k] (j<=k<=3) } (當第i個數爲j時,不需更改)
邊界條件
* F[0,k]=G[0,k]=0 (1<=k<=3)
目標結果
* Ans=Min{F[N,i],G[N,i]} (1<=i<=3)
/*
ID: cmykrgb1
PROG: egroup
LANG: C++
*/
#include <iostream>
#define INF 0x7FFFFFFF
#define MAX 30001
using namespace std;
int F[MAX][4];
int S[MAX];
int N,Ans=INF;
void init()
{
int i;
freopen("egroup.in","r",stdin);
freopen("egroup.out","w",stdout);
cin >> N;
for (i=1;i<=N;i++)
cin >> S[i];
}
void dynamic()
{
int i,j,k;
for (j=1;j<=3;j++)
{
for (i=1;i<=N;i++)
{
F[i][j]=INF;
for (k=1;k<=j;k++)
{
if (F[i-1][k]<F[i][j])
F[i][j]=F[i-1][k];
}
if (S[i]!=j)
F[i][j]++;
}
if (F[N][j]<Ans)
Ans=F[N][j];
}
for (j=3;j>=1;j--)
{
for (i=1;i<=N;i++)
{
F[i][j]=INF;
for (k=j;k<=3;k++)
{
if (F[i-1][k]<F[i][j])
F[i][j]=F[i-1][k];
}
if (S[i]!=j)
F[i][j]++;
}
if (F[N][j]<Ans)
Ans=F[N][j];
}
}
int main()
{
init();
dynamic();
cout << Ans << endl;
return 0;
}