https://vjudge.net/problem/ZOJ-3469
题意:
在一条直线上有一个餐厅和n个订餐的人,每个人都有随时间上升的不满意值,从餐厅出发,计算出送完时最小的不满意值总和。
思路:
这道题和UVa 1632这道题目很像,只不过1632可以从任一点出发,而这题必须从餐厅出发。1632每个坐标几秒之后就会消失,这题是每分钟不满意值会上升,比较类似,都是挺不错的区间DP题。
d[i][j][0]代表的是在送完i~j这个区间的最小不满意值,并且此时人处于左端,d[i][j][1]则是人处于右端。
状态转移的话看代码吧,d[i][j][]的话可以从d[i+1][j][]过来,也可以从d[i][j-1][]过来。
1 #include<iostream> 2 #include<cstring> 3 #include<string> 4 #include<algorithm> 5 using namespace std; 6 7 #define INF 0x3f3f3f3f 8 const int maxn = 1000 + 5; 9 10 int n, v, x; 11 12 struct node 13 { 14 int x, b; 15 }p[maxn]; 16 17 int sum[maxn]; 18 int d[maxn][maxn][2]; 19 20 bool cmp(node a, node b) 21 { 22 return a.x < b.x; 23 } 24 25 int main() 26 { 27 //freopen("D:\txt.txt", "r", stdin); 28 while (cin >> n >> v >> x) 29 { 30 for (int i = 0; i < n; i++) 31 cin >> p[i].x >> p[i].b; 32 33 //出发点 34 p[n].x = x; 35 p[n].b = 0; 36 sort(p, p + n +1, cmp); 37 38 for (int i = 0; i <= n; i++) 39 for (int j = 0; j <= n; j++) 40 d[i][j][0] = d[i][j][1] = INF; 41 42 //前i个顾客的不满意度之和 43 sum[0] = p[0].b; 44 for (int i = 1; i <= n; i++) 45 { 46 sum[i] = sum[i - 1] + p[i].b; 47 } 48 49 int k; 50 for (int i = 0; i <= n; i++) 51 { 52 if (p[i].x == x) 53 { 54 d[i][i][0] = d[i][i][1] = 0; 55 k = i; 56 break; 57 } 58 } 59 60 for (int i = k; i >= 0;i--) 61 for (int j = k; j <= n; j++) 62 { 63 if (i == j) continue; 64 d[i][j][0] = min(d[i][j][0], d[i + 1][j][0] + (p[i + 1].x - p[i].x)*(sum[n] + sum[i] - sum[j])); 65 d[i][j][0] = min(d[i][j][0], d[i + 1][j][1] + (p[j].x - p[i].x)*(sum[n] + sum[i] - sum[j])); 66 d[i][j][1] = min(d[i][j][1], d[i][j - 1][1] + (p[j].x - p[j - 1].x)*(sum[n] - sum[j - 1] + sum[i - 1])); 67 d[i][j][1] = min(d[i][j][1], d[i][j - 1][0] + (p[j].x - p[i].x)*(sum[n] - sum[j - 1] + sum[i - 1])); 68 } 69 cout << min(d[0][n][0], d[0][n][1])*v << endl; 70 } 71 }