首页 > 代码库 > BZOJ 1609: [Usaco2008 Feb]Eating Together
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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。