Beyond the Void
BYVoid
USACO FEB08 Silver Eating Together 麻煩的聚餐
本文正體字版由OpenCC轉換

由於結果要分兩種情況(不下降序列和不上升序列),要進性兩遍動態規劃

狀態設定

* 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;
}

上次修改時間 2017-02-03

相關日誌