bzoj1609[Usaco2008 Feb]Eating Together麻烦的聚餐*

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

题意:

一个序列只由1﹑2﹑3三种数组成。求最少要改变多少个数使它变成不下降序列或不上升序列。序列大小≤30000

题解:

DP。设f[i][j]表示正在考虑第i个数,上一个数是j。求不下降序列最少改变个数方程:

f[i][j]=min(f[i+1][k]+1,k∈[j,3]),a[i]<j
          min(f[i+1][a[i]],f[i+1][k]+1,k∈[j,3]且k!=a[i])a[i]>=j

求不上升同理。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define maxn 50000
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define dec(i,j,k) for(int i=j;i>=k;i--)
 7 #define INF 0x3fffffff
 8 using namespace std;
 9 
10 int n,a[maxn],x[5],y[5],ans;
11 int main(){
12     scanf("%d",&n); inc(i,1,n)scanf("%d",&a[i]); memset(x,0,sizeof(x));
13     dec(i,n,1){
14         memset(y,0,sizeof(y));
15         inc(j,1,3)if(a[i]<j){
16             y[j]=INF; inc(k,j,3)y[j]=min(y[j],x[k]+1);
17         }else{
18             y[j]=x[a[i]]; inc(k,j,3)if(k!=a[i])y[j]=min(y[j],x[k]+1);
19         }
20         swap(x,y);
21     }
22     ans=INF; inc(i,1,3)ans=min(ans,x[i]); memset(x,0,sizeof(x));
23     dec(i,n,1){
24         memset(y,0,sizeof(y));
25         inc(j,1,3)if(a[i]>j){
26             y[j]=INF; dec(k,j,1)y[j]=min(y[j],x[k]+1);
27         }else{
28             y[j]=x[a[i]]; dec(k,j,1)if(k!=a[i])y[j]=min(y[j],x[k]+1);
29         }
30         swap(x,y);
31     }
32     inc(i,1,3)ans=min(ans,x[i]); printf("%d",ans); return 0;
33 }

 

20160729

posted @ 2016-07-29 22:47  YuanZiming  阅读(221)  评论(0编辑  收藏  举报