1609[Usaco2008 Feb]Eating Together麻烦的聚餐
Posted Blue233333
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1609[Usaco2008 Feb]Eating Together麻烦的聚餐相关的知识,希望对你有一定的参考价值。
题目大意:把一个只含1,2,3的序列改成形如111……222……333……或333……222……111……的形式最少改几个数。
题解:光看这个数列无从知晓答案,所以试着采用DP。由于每个数变1,2,3与后面的数怎么变密切相关,所以F[i][j]表示前i个数中,第i个数变j后满足第一种形态的最少次数,则有F[i][j]=F[i-1][k]+diff(a[i],j),其中k∈[1,j],diff(a,b)表示a,b是否不同。形态2的话,既可以把上式的“i-1”改为“i+1”,又可以把整个序列前后颠倒再搞一次,非常自由。
代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cctype> using namespace std; int qread() { char c;int s=0; while (!isdigit(c=getchar())); do {s=s*10+c-\'0\';} while (isdigit(c=getchar())); return s; } int n; #define maxn 30233 int a[maxn],f[maxn][5]; #define inf 0x7fffffff int dif(int x,int y) { return (x==y?0:1); } void solve() { for (int j=1;j<=3;j++) f[0][j]=0; for (int i=1;i<=n;i++) for (int j=1;j<=3;j++) { f[i][j]=inf; int d=dif(a[i],j); for (int k=j;k;k--) f[i][j]=min(f[i][j],f[i-1][k]+d); } } int main() { n=qread(); for (int i=1;i<=n;i++) a[i]=qread(); solve(); int ans1=min(f[n][1],min(f[n][2],f[n][3])); for (int i=1;i<=n/2;i++) {int t=a[i];a[i]=a[n-i+1];a[n-i+1]=t;} solve(); int ans2=min(f[n][1],min(f[n][2],f[n][3])); printf("%d\\n",min(ans1,ans2)); return 0; }
以上是关于1609[Usaco2008 Feb]Eating Together麻烦的聚餐的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1609: [Usaco2008 Feb]Eating Together
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)