断环然后裸DP就好了。。。

$f[i][j][k]$表示1号时间段没有被算入答案,到了第$i$个时间段,一共选了$j$个时间段,$k = 0 /1$表示第i个时间段有没有被算进答案的最优值

$g[i][j][k]$表示1号时间段被算入答案,到了第$i$个时间段,一共选了$j$个时间段,$k = 0 /1$表示第i个时间段有没有被算进答案的最优值,则$g$必须要选最后一个时间段

转移的时候直接枚举最后一个时间段又没有被算进答案就好了。。。方程看程序好了。。

 

 

 1 /**************************************************************
 2     Problem: 1737
 3     User: rausen
 4     Language: C++
 5     Result: Accepted
 6     Time:92 ms
 7     Memory:948 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #include <algorithm>
12  
13 using namespace std;
14 const int N = 4e3 + 5;
15 const int inf = 1e9;
16  
17 inline int read();
18  
19 int n, m;
20 int v[N];
21 int f[2][N][2], g[2][N][2];
22  
23 int main() {
24     int i, j, now, last;
25     n = read(), m = read();
26     for (i = 1; i <= n; ++i) v[i] = read();
27     for (i = 0; i <= m; ++i)
28         for (j = 0; j < 2; ++j) f[1][i][j] = g[1][i][j] = -inf;
29     f[1][0][0] = f[1][1][1] = g[1][1][1] = 0;
30     for (i = 2; i <= n; ++i) {
31         now = i & 1, last = !now;
32         for (j = 0; j <= m; ++j) {
33             f[now][j][0] = max(f[last][j][1], f[last][j][0]);
34             g[now][j][0] = max(g[last][j][1], g[last][j][0]);
35             if (j) {
36                 f[now][j][1] = max(f[last][j - 1][0], f[last][j - 1][1] + v[i]);
37                 g[now][j][1] = max(g[last][j - 1][0], g[last][j - 1][1] + v[i]);
38             } else
39                 f[now][j][1] = g[now][j][1] = -inf;
40         }
41     }
42     printf("%d\n", max(f[n & 1][m][0], max(f[n & 1][m][1], g[n & 1][m][1] + v[1])));
43     return 0;
44 }
45  
46 inline int read() {
47     static int x;
48     static char ch;
49     x = 0, ch = getchar();
50     while (ch < '0' || '9' < ch)
51         ch = getchar();
52     while ('0' <= ch && ch <= '9') {
53         x = x * 10 + ch - '0';
54         ch = getchar();
55     }
56     return x;
57 }
View Code

 

posted on 2015-04-29 22:19  Xs酱~  阅读(341)  评论(0编辑  收藏  举报