[luoguP2896] [USACO08FEB]一起吃饭Eating Together(DP)

传送门

 

由于 Di 只有 3 种情况,那么就很简单了

 

f[i][j][0] 表示前 i 个,且第 i 个变成 j 的 递增序列最小修改次数

f[i][j][1] 表示前 i 个,且第 i 个变成 j 的 递减序列最小修改次数

状态转移看代码。

 

——代码

 1 #include <cstdio>
 2 #include <iostream>
 3 
 4 const int MAXN = 30001;
 5 int n, ans = ~(1 << 31);
 6 int a[MAXN], f[MAXN][4][2];
 7 
 8 inline long long read()
 9 {
10     long long x = 0, f = 1;
11     char ch = getchar();
12     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
13     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
14     return x * f;
15 }
16 
17 inline int min(int x, int y)
18 {
19     return x < y ? x : y;
20 }
21 
22 int main()
23 {
24     int i, j;
25     n = read();
26     for(i = 1; i <= n; i++) a[i] = read();
27     for(i = 1; i <= n; i++)
28     {
29         f[i][1][0] = f[i - 1][1][0] + (a[i] != 1);
30         f[i][2][0] = min(f[i - 1][1][0], f[i - 1][2][0]) + (a[i] != 2);
31         f[i][3][0] = min(f[i - 1][1][0], min(f[i - 1][2][0], f[i - 1][3][0])) + (a[i] != 3);
32         
33         f[i][1][1] = min(f[i - 1][1][1], min(f[i - 1][2][1], f[i - 1][3][1])) + (a[i] != 1);
34         f[i][2][1] = min(f[i - 1][3][1], f[i - 1][2][1]) + (a[i] != 2);
35         f[i][3][1] = f[i - 1][3][1] + (a[i] != 3);
36     }
37     for(i = 1; i <= 3; i++)
38         for(j = 0; j <= 1; j++)
39             ans = min(ans, f[n][i][j]);
40     printf("%d\n", ans);
41     return 0;
42 }
View Code

 

posted @ 2017-05-26 11:12  zht467  阅读(242)  评论(0编辑  收藏  举报