Description

IOI 铁路是由 N+2 个站点构成的直线线路. 这条线路的车站从某一端的车站开始顺次标号为 \(0, 1, 2, \ldots, n+1\).

这条路线上行驶的电车分为上行电车和下行电车两种, 上行电车沿编号增大方向行驶, 下行 电车沿编号减小方向行驶. 乘坐这两种电车的话, 移动 \(1\) 站的距离需要 \(t\) 秒. 换句话说, 乘坐上行电车从车站 \(i\) 走到车站 \(i+1\) 需要 \(t\) 秒, 乘坐下行电车从车站 \(i\) 走到车站 \(i-1\) 也需要 \(t\) 秒. 你不能在 \(0\) 号车站乘坐下行电车, 或在 \(n+1\) 号车站乘坐上行电车. 由于电车发车的频率非常高, 你可以无视等待电车消耗的时间.

每个车站设有上行电车的站台和下行电车的站台, 连接两个站台的道路上设有邮戳台.

现在, IOI 铁路召开了邮戳拉力赛. 在拉力赛中, 选手需要从 \(0\) 号车站的上行电车站台 出发, 在 \(1, 2, \ldots, n\) 号车站各盖一枚邮戳, 最终到达 \(n+1\) 号车站的上行电车 站台即可完成.

为了在每个车站盖上邮戳, 必须从电车上下来, 步行走到车站通路上的邮戳台. 在 \(i\) 号车站的上行电车站台、邮戳台、下行电车站台之间移动所消耗的时间如下所示:

  • 从车站 \(i\) 的上行电车站台到邮戳台的时间为 \(U_i\)
  • 从车站 \(i\) 的邮戳台到上行电车站台的时间为 \(V_i\)
  • 从车站 \(i\) 的下行电车站台到邮戳台的时间为 \(D_i\)
  • 从车站 \(i\) 的邮戳台到下行电车站台的时间为 \(E_i\)

邮戳拉力赛的选手只能访问 \(0\) 号车站与 \(n+1\) 号车站各一次.\(1, 2, \ldots, n\) 号车站都可以访问任意多次.

现在给出有邮戳台的车站个数、乘坐电车移动一站的时间、在每个车站的上行电车站台、邮戳台、下行电车站台之间移动所消耗的时间, 请你求出完成邮戳拉力赛的最短时间.

这个时间包括从 \(0\) 号车站出发, 按下 \(n\) 个邮戳后到达 \(n+1\) 号车站的时间. 无视 等车的时间和按邮戳的时间.

Input

第一行两个空格分隔的整数 \(n, t\), 表示有 \(n+2\) 个车站, 电车行驶一站的距离需要 \(t\) 秒;

接下来 \(n\) 行, 第 \(i\) 行有四个空格分隔的整数 \(U_i, V_i, D_i, E_i\), 分别表示题干中表示的含义.

Output

输出一行一个整数, 表示完成邮戳拉力赛的最短时间.

Sample Input

4 1
1 1 1 1
1 9 9 1
9 9 1 1
1 9 9 1

Sample Output

23

Data Range

对于所有数据, 满足:\(1 \leq n \leq 3000, 1 \leq t \leq 10^5, 1 \leq U_i, V_i, D_i, E_i \leq 10^5\)

Explanation

一道很奇怪的背包问题......

因为所有人都要从左边走到右边对吧...... 而且反反复复走很多遍一点意义都没有对吧...... 所以只会出现几个往回走的环, 而且环一般不会交叉 (逃).

然后只要统计这些环出现的次数与当前的位置的关系就可以了.

然后 \(dp[i][j]\) 表示在第 \(i\) 个位置, 从上行站台走到下行站台比 (反之) 多的次数为 \(j\) 的最短时间.

Source Code


#include <iostream>
#include <cstdlib>
#include <cstdio>

#define rep(_var,_begin,_end) for(int _var=_begin;_var<=_end;_var++)
#define range(_begin,_end) rep(_,_begin,_end)
#define minimize(__x,__y) __x=min(__x,__y)
using namespace std;
typedef long long lli;
const int maxn = 3010;
const lli infinit = 0x007f7f7f7f7f7f7fll;

int n, t;
lli dp[maxn][maxn];
int u[maxn], v[maxn], d[maxn], e[maxn];

int main(int argc, char** argv)
{
    scanf("%d%d", &n, &t);
    for (int i = 1; i <= n; i++)
        scanf("%d%d%d%d", &u[i], &v[i], &d[i], &e[i]);
    // Setting large limits
    rep(i, 0, n+1) rep(j, 0, n+1)
        dp[i][j] = infinit;
    // Knapsack problem
    dp[0][0] = 0;
    rep(i, 1, n) {
        range(0,n) dp[i-1][_] += _*t*2;
        #define update(__x) minimize(dp[i][j],__x);
        rep(j,0,n-1) update(dp[i-1][j+1] + u[i] + e[i]);
        rep(j,1,n) update(dp[i-1][j-1] + d[i] + v[i]);
        rep(j,0,n) update(dp[i-1][j] + u[i] + v[i]);
        rep(j,1,n) update(dp[i-1][j] + d[i] + e[i]);
        rep(j,0,n-1) update(dp[i][j+1] + u[i] + e[i]);
        rep(j,1,n) update(dp[i][j-1] + d[i] + v[i]);
    }
    lli res = dp[n][0] + t*(n+1);
    printf("%lld\n", res);
    return 0;
}