摆渡车

题目描述:
\(n\) 名同学要乘坐摆渡车从人大附中前往人民大学,第 iii 位同学在第 \(t_i\) 分钟去 等车。只有一辆摆渡车在工作,但摆渡车容量可以视为无限大。摆渡车从人大附中出发、 把车上的同学送到人民大学、再回到人大附中(去接其他同学),这样往返一趟总共花费\(m\)分钟(同学上下车时间忽略不计)。摆渡车要将所有同学都送到人民大学。

凯凯很好奇,如果他能任意安排摆渡车出发的时间,那么这些同学的等车时间之和最小为多少呢?

注意:摆渡车回到人大附中后可以即刻出发。

数据范围:
\(n \leq 500,m \leq 100,t_i \leq 4 \times 10^6\)

题解:

有一个显而易见的事情,如果第\(i\)个人到达了这里,那么在保证最优的情况下他一定是在\([t_i,t_i + m)\)乘车去人大的。

那么我们就可以得到一个dp,设\(f[i][j]\)表示第\(i\)个人在\([t_i,t_i + j)\)出发的等待时间总和最小值。

转移暴力枚举即可。

适当的用前缀和优化一下转移方程即可AC。

#include <bits/stdc++.h>
#include <climits>
using namespace std;
#define INF 0x3f3f3f3f
#define rep(i,_,__) for(int i = _;i <= __; ++i)
const int MAXN = 1010;
typedef pair<int,int> P;
#define mk(x,y) make_pair(x,y)
#define fir first
#define sec second
P range[MAXN];
int read () {
    int q=0,f=1;char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')f=-1;ch=getchar();
    }
    while(isdigit(ch)){
        q=q*10+ch-'0';ch=getchar();
    }
    return q*f;
}
int f[MAXN][MAXN];
int t[MAXN];
int ans;
int sum[MAXN];
int n,m;
int main () {
    n = read(),m = read();
    rep(i,1,n) {
        t[i] = read();
    }
    sort(t + 1,t + n + 1);
    rep(i,1,n) {
        f[i][0] = INF;
        rep(j,0,min(t[i] - t[i - 1] - m,m - 1)) {
            f[i][0] = min(f[i][0],f[i - 1][j]);
        }
        rep(j,1,(m << 1) - 1) {
            if(t[i] - t[i - 1] + j - m >= 0 and t[i] - t[i - 1] + j - m < (m << 1)) {
                f[i][j] = min(f[i][j - 1],f[i - 1][t[i] - t[i - 1] + j - m]);
            }
            else {
                f[i][j] = min(f[i][j - 1],INF);
            }
        }
        rep(j,0,(m << 1) - 1) {
            if(t[i] - t[i - 1] + j < (m << 1)) {
                f[i][j] = min(f[i][j],f[i - 1][t[i] - t[i - 1] + j]) + j;
            }
            else {
                f[i][j] = min(f[i][j],INF) + j;
            }
        }
    }
    ans = INT_MAX;
    rep(i,0,m) {
        ans = min(ans,f[n][i]);
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/akoasm/p/10121009.html
今日推荐