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