题目链接:
题目描述:
在x轴上有n个客人叫外卖,每个顾客因为追的番更新进度不同,所以在等外买的时间里每秒增加的愤怒值不同。给出客人和餐厅的位置,以及客人每分钟增加的愤怒值,还有快递小哥的行走一公里需要的时间。问送完外卖后n个客人的最小愤怒值?
解题思路:
区间DP,大一的时候做省赛练习的时候见过这种类型的题目,但是今天遇到由于年代久远,还是GG······。
把餐厅所在的点加进去,然后按照在x轴上的位置排序。从餐厅所在位置向左右开始DP,dp[x][y][z] 代表 处理完区间[y, z]停留在x方向的最小花费,这个题目要预处理未加进去点的花费。然后选取最优。
1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 typedef long long LL; 8 const int INF = 0x3f3f3f3f; 9 const int maxn = 1010; 10 struct node 11 { 12 int x, b; 13 } p[maxn]; 14 LL dp[2][maxn][maxn], sum[maxn];//dp[0][x][y]左边 区间[x, y], dp[1][x][y]右边 区间[x, y] 15 16 bool cmp (node a, node b) 17 { 18 return a.x < b.x; 19 } 20 21 int main () 22 { 23 int n, v, x; 24 while (scanf ("%d %d %d", &n, &v, &x) != EOF) 25 { 26 for (int i=1; i<=n; i++) 27 scanf ("%d %d", &p[i].x, &p[i].b); 28 p[++n].x = x; 29 p[n].b = 0; 30 sort (p+1, p+n+1, cmp); 31 32 for (int i=0; i<=n; i++) 33 for (int j=0; j<=n; j++) 34 dp[0][i][j] = dp[1][i][j] = INF; 35 int tem = 0; 36 for (int i=1; i<=n; i++) 37 if (p[i].x == x) 38 { 39 tem = i; 40 break; 41 } 42 dp[0][tem][tem] = dp[1][tem][tem] = 0; 43 44 sum[0] = 0; 45 for (int i=1; i<=n; i++) 46 sum[i] = sum[i-1] + p[i].b; 47 48 49 for (int i=tem; i>0; i--) 50 for (int j=tem; j<=n; j++) 51 { 52 if (i == j) continue; 53 dp[0][i][j] = min (dp[0][i][j], dp[0][i+1][j]+(sum[n]-sum[j]+sum[i])*(p[i+1].x - p[i].x)); 54 dp[0][i][j] = min (dp[0][i][j], dp[1][i+1][j]+(sum[n]-sum[j]+sum[i])*(p[j].x - p[i].x)); 55 56 dp[1][i][j] = min (dp[1][i][j], dp[1][i][j-1]+(sum[n]-sum[j-1]+sum[i-1])*(p[j].x - p[j-1].x)); 57 dp[1][i][j] = min (dp[1][i][j], dp[0][i][j-1]+(sum[n]-sum[j-1]+sum[i-1])*(p[j].x - p[i].x)); 58 } 59 printf ("%lld ", v * min (dp[0][1][n], dp[1][1][n])); 60 } 61 return 0; 62 }