写着写着越来越觉得是dfs,dp写的不知道哪里出问题了。
1 # include <stdio.h>
2 # include <string.h>
3
4 # define INF 1<<30
5 # define MAXN 1002
6
7 # define MIN(x,y) ((x)<(y) ? (x):(y))
8
9 int n, v;
10 int p[MAXN];
11 int d[MAXN];
12 int vis[MAXN];
13 long long int f[MAXN][MAXN]; /* 子问题f[i][j]:下一个关的是 i 或 j 时,关掉所有灯的最小能耗 */
14 int sp[MAXN][MAXN]; /* sp[i][j]: 所有灯的功率减去 i+1...j-1 号灯的总功率 */
15
16 long long dp(int i, int j); /* 记忆化搜索 */
17
18 int main()
19 {
20 int i, j, k, sumP;
21
22 while (~scanf("%d%d", &n, &v))
23 {
24 for ( sumP = 0, i = 1; i <= n; ++i)
25 {
26 scanf("%d%d", &d[i], &p[i]);
27 sumP += p[i];
28 }
29
30 memset(f, 0, sizeof(f));
31 memset(sp, 0, sizeof(sp));
32 memset(vis, 0, sizeof(vis));
33
34 /* 计算sp[i][j], 其中i<=v, j>=v */
35 for ( i = 1; i < v; ++i)
36 for ( j = v+1; j <= n; ++j)
37 for ( sp[i][j] = sumP, k = i+1; k < j; ++k)
38 sp[i][j] -= p[k];
39
40 printf("%lld\n", dp(v-1, v+1));
41 }
42
43 return 0;
44 }
45
46 long long int dp(int i, int j)
47 {
48 long long int t;
49 int k;
50
51 if ( f[i][j] > 0) return f[i][j];
52
53 /* 第一次走到第一个灯前并关掉它后,只要关掉右面的 j...n 号灯即可 */
54 if ( i == 0)
55 {
56 for ( f[i][j] = 0, k = j; k <= n; ++k)
57 f[i][j] += (d[k]-d[1])*p[k];
58 return f[i][j];
59 }
60
61 /* 第一次走到最后一个灯前并关掉它后,只要关掉右面的 1...i 号灯即可 */
62 if ( j == n+1)
63 {
64 for ( f[i][j] = 0, k = 1; k <= i; ++k)
65 f[i][j] += (d[n]-d[k])*p[k];
66 return f[i][j];
67 }
68
69 /* 其它分四种情况 */
70 f[i][j] = INF;
71 if (!vis[i+1])
72 {
73 vis[i+1] = 1;
74 if ((t = dp(i-1, j)+(d[i+1]-d[i])*sp[i][j]) < f[i][j]) f[i][j] = t;
75 if ((t = dp(i, j+1)+(d[j]-d[i+1])*sp[i][j]) < f[i][j]) f[i][j] = t;
76 vis[i+1] = 0;
77 }
78 if (!vis[j-1])
79 {
80 vis[j-1] = 1;
81 if ((t = dp(i-1, j)+(d[j-1]-d[i])*sp[i][j]) < f[i][j]) f[i][j] = t;
82 if ((t = dp(i, j+1)+(d[j]-d[j-1])*sp[i][j]) < f[i][j]) f[i][j] = t;
83 vis[j-1] = 0;
84 }
85
86 return f[i][j];
87 }