Beyond the Void
BYVoid
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;
}

上次修改时间 2017-02-03

相关日志