BZOJ 1609: [Usaco2008 Feb]Eating Together

Posted nhc2014

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1609: [Usaco2008 Feb]Eating Together相关的知识,希望对你有一定的参考价值。

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1609

解:题目很明显,我们只要找到最长不下降子序列,然后总长度减去它的长度就可以了,用o(nlogn)的方法。

但是,用O(9n)的动归,显然更优(吧。。。)

我学习了一下他人的动归。

用f[i][j](1<=i<=n;j=1,2,3)来表示序列前i个的时候,我们当前用j

这个数字结尾最多需要改几个。当然我们还要枚举上一段的位置,具体我程序里写吧。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int f[40000][4],f2[40000][4],n,a[40000];
int dp()
{
   for (int i=1;i<=n;i++)
   for (int j=1;j<=3;j++)
    f[i][j]=i;
//初始化
  for (int i=1;i<=n;i++)
  {
    for (int j=1;j<=3;j++)
    for (int k=1;k<=j;k++)
//枚举上一次是哪种状态,且这种状态必须小于等于j
//如果相等的话直接更新就行
    if (a[i]==j) f[i][j]=min(f[i][j],f[i-1][k]);
//否则还要更改当前的这个
    else f[i][j]=min(f[i][j],f[i-1][k]+1);
  }
  return (min(min(f[n][1],f[n][2]),f[n][3]));
}
int main()
{
  scanf("%d",&n);
  for (int i=1;i<=n;i++) scanf("%d",&a[i]);
  int ans=dp();
//正着来一遍,反着来一遍
  for (int i=1;i<=n/2;i++) {int t=a[i];a[i]=a[n-i+1];a[n-i+1]=t;}
  ans=min(ans,dp());
  printf("%d\n",ans);
  return 0;
}

 

以上是关于BZOJ 1609: [Usaco2008 Feb]Eating Together的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1609: [Usaco2008 Feb]Eating Together

[BZOJ1609] [Usaco2008 Feb] Eating Together麻烦的聚餐 (dp)

BZOJ_1609_[Usaco2008_Feb]_Eating_Together_麻烦的聚餐_(LIS)

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

BZOJ 1609 [Usaco2008 Feb]Eating Together麻烦的聚餐:LIS & LDS (nlogn)

1609[Usaco2008 Feb]Eating Together麻烦的聚餐