[CodeForces - 853B] Jury Meeting 【前后缀 + 贪心】

 题意:

  • 城市[1, n]的jury要到城市0去,要求在城市0至少待够k天。给出所有的航班信息(城市i - 0的航班 || 城市0 - i的航班),每个航班有它飞的时间,以及它的消费。【jury到达或离开城市0的当天不能算于k天】问:所有城市的jury在城市0能待够至少k天的最小花费是多少?

思路:

  • 定义dp[2][ ],其中dp[0][ i ]:表示第i天所有jury全部到达城市0的最小花费;dp[1][ i ]:表示第i天所有jury能离开城市0的最小花费。
  • 显然dp[0]很好理解,前i天,我们只需要维护每个城市的jury到达城市0的最小花费,就能维护所有城市jury到达城市0的最小花费
  • 而dp[1]则是倒着维护,假设dp[1][10]走完了所有的jury,那么dp[1][9]也肯定可以走完所有的jury,这时候只需要维护最小花费即可
  • 将所有1e6之内的dp[0]和dp[1]全部更新,那么我们就以长度k的尺子来尺取最小值即可!(也就是不需要考虑大于k的情况,具体见代码)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#define INF 0x3f3f3f3f3f
using namespace std;

typedef long long ll;

inline int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -f; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}

const int maxN = 100005;
const int maxM = 1000006;

int n, m, k;
struct node{
    int day, city; ll cost;
    friend bool operator < (node &n1, node &n2) { return n1.day < n2.day; }
}in[maxN], out[maxN];

ll dp[2][maxM];
int vis[maxN];

int main()
{
    n = read(); m = read(); k = read();
    int inNum = 0, outNum = 0;
    for(int i = 0; i < m; ++ i )
    {
        int d, s, e, w;
        d = read(); s = read(); e = read(); w = read();
        if(s) in[inNum ++ ] = node{d, s, w};
        else out[outNum ++ ] = node{d, e, w};
    }
    sort(in, in + inNum);
    sort(out, out + outNum);
    int num = 0; ll sum = 0;
    memset(dp, INF, sizeof(dp));
    memset(vis, -1, sizeof(vis));
    for(int i = 0; i < inNum; ++ i )    //去
    {
        if(vis[in[i].city] == -1)
            vis[in[i].city] = in[i].cost, ++ num, sum += in[i].cost;
        else if(in[i].cost < vis[in[i].city])
            sum -= vis[in[i].city], sum += in[i].cost, vis[in[i].city] = in[i].cost;
        if(num == n)
            dp[0][in[i].day] = sum;
    }
    num = 0;  sum = 0;
    memset(vis, -1, sizeof(vis));
    for(int i = outNum - 1; i >= 0; -- i )    //回
    {
        if(vis[out[i].city] == -1)
            vis[out[i].city] = out[i].cost, ++ num, sum += out[i].cost;
        else if(out[i].cost < vis[out[i].city])
            sum -= vis[out[i].city], sum += out[i].cost, vis[out[i].city] = out[i].cost;
        if(num == n)
            dp[1][out[i].day] = sum;
    }
    for(int i = 1; i < maxM; ++ i )
        dp[0][i] = min(dp[0][i - 1], dp[0][i]);
    for(int i = maxM - 2; i >= 1; -- i)
        dp[1][i] = min(dp[1][i + 1], dp[1][i]);
    ll ans = INF;
    for(int i = 1; i + k + 1 < maxM; ++ i )
        ans = min(ans, dp[0][i] + dp[1][i + k + 1]);
    if(ans == INF) printf("-1\n");
    else printf("%lld\n", ans);
    return 0;
}
发布了242 篇原创文章 · 获赞 68 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/104590021
今日推荐