csu 1141 节能

记忆化搜索,dp;

前面WA的原因是状态转移时,对机器人位置的转移考虑补充分,使用vis[]标记只能保证相邻的状态的转移是正确的;

需要增加一个额外的参数标记机器人所在位置,这样在递归时才能保证状态的转移是正确的(不会交叉);

感谢LJ大牛!感谢C++!(使用C提交超时,原因不明,排除了OJ的原因,对数据预处理的C代码很快通过,百度"C++比C快"的结果都是C比C++快,无语)。

 1 # include <cstdio>
2 # include <iostream>
3 # include <cstring>
4
5 using namespace std;
6
7 # define LEFT 0
8 # define RIGHT 1
9 # define MAXN 1002
10
11 int n, v, sumP;
12 int p[MAXN], d[MAXN];
13 int t[MAXN][MAXN][2];
14
15 /*
16 int min(int x, int y)
17 {
18 return (x<y ? x:y);
19 }
20 */
21 int dp(int s, int e, int r);
22
23 int main()
24 {
25 int i;
26
27 while (~scanf("%d%d", &n, &v))
28 {
29 for (sumP = 0, i = 1; i <= n; ++i)
30 {
31 scanf("%d%d", &d[i], &p[i]);
32 sumP += p[i];
33 }
34
35 memset(t, 0, sizeof(t));
36
37 printf("%d\n", dp(v-1, v+1, LEFT));
38 }
39
40 return 0;
41 }
42
43 int dp(int s, int e, int r)
44 {
45 int k, pt, x, y;
46
47 if (t[s][e][r] > 0) return t[s][e][r];
48
49 if (s == 0)
50 {
51 for (t[s][e][r] = 0, k = e; k <= n; ++k)
52 t[s][e][r] += (d[k]-d[1])*p[k];
53 return t[s][e][r];
54 }
55 if (e == n+1)
56 {
57 for (t[s][e][r] = 0, k = 1; k <= s; ++k)
58 t[s][e][r] += (d[n]-d[k])*p[k];
59 return t[s][e][r];
60 }
61
62 for (pt = sumP, k = s+1; k < e; ++k)
63 pt -= p[k];
64
65 if (r == LEFT)
66 {
67 x = dp(s-1, e, LEFT)+(d[s+1]-d[s])*pt;
68 y = dp(s, e+1, RIGHT)+(d[e]-d[s+1])*pt;
69 /* t[s][e][r] = min(dp(s-1, e, LEFT)+(d[s+1]-d[s])*pt,
70 dp(s, e+1, RIGHT)+(d[e]-d[s+1])*pt); */
71 return t[s][e][r] = (x<y ? x:y);
72 }
73 else
74 {
75 x = dp(s, e+1, RIGHT)+(d[e]-d[e-1])*pt;
76 y = dp(s-1, e, LEFT)+(d[e-1]-d[s])*pt;
77 /* t[s][e][r] = min(dp(s, e+1, RIGHT)+(d[e]-d[e-1])*pt,
78 dp(s-1, e, LEFT)+(d[e-1]-d[s])*pt); */
79 return t[s][e][r] = (x<y ? x:y);
80 }
81 }
原文地址:https://www.cnblogs.com/JMDWQ/p/2433481.html