zoj 3469 区间dp 三维

题意:

x轴上有n个人,每个人所在位置为xi,对应一个bi值,餐厅坐标为x,送货员速度为1/v 米/分钟,送货员的后备箱中有所有客人的饭,不用中途回去。没有收到饭的客人每分钟不开心值增加bi。求总不开心值的最小值。1 <= n <= 1000。

题解:

1.n的范围就决定了不能用前几道题写的O(n^3)算法。这个不是简单的区间合并,而是每次增加一个端点。[i , j]的客人都送完时送货员一定在端点处的i或者j

2.dp[i][j][0]表示[i , j]送完后送货员在i处的总不开心值的最小值dp[i][j][1]表示[i , j]送完后送货员在j处的总不开心值的最小值

3.状态转移方程在代码中,一目了然,sum[i]表示的是[1,i]的不开心值和。

#include <bits/stdc++.h>
#define N 1005
#define inf 0x3f3f3f3f
using namespace std;
int dp[N][N][2] ;
struct Node
{
    int x , b ;
} node[N] ;
bool cmp(Node a , Node b)
{
    return a.x < b.x ;
}
int main()
{
    int n , v , x ;
    int i , j , d ;
    int sum[N] ;
    while(scanf("%d%d%d" , &n , &v , &x) != EOF)
    {
      for(i = 1 ; i <= n ; i ++)
        scanf("%d%d" , &node[i].x , &node[i].b) ;
      sort(node + 1 , node + n + 1 , cmp) ;
      sum[0] = 0 ;
      for(i = 1 ; i <= n ; i ++)
        sum[i] = sum[i - 1] + node[i].b ;
      memset(dp , inf , sizeof(inf)) ;
      for(i = 1 ; i <= n ; i ++)
        dp[i][i][0] = dp[i][i][1] = abs(x - node[i].x) * sum[n] ;
      for(d = 1 ; d <= n - 1 ; d ++)
        for(i = 1 ; i + d <= n ; i ++)
        {
            j = i + d ;
            dp[i][j][0] = min(dp[i + 1][j][0] + (node[i + 1].x - node[i].x) * (sum[i] + sum[n] - sum[j]) ,
                              dp[i + 1][j][1] + (node[j].x - node[i].x) * (sum[i] + sum[n] - sum[j])) ;
            dp[i][j][1] = min(dp[i][j - 1][0] + (node[j].x - node[i].x) * (sum[i - 1] + sum[n] - sum[j - 1]) ,
                              dp[i][j - 1][1] + (node[j].x - node[j - 1].x) * (sum[i - 1] + sum[n] - sum[j - 1])) ;
        }
      printf("%d\n" , min(dp[1][n][0] * v , dp[1][n][1] * v)) ;
    }
}

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/87973442