断环然后裸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 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen