Codeforces Gym 101173 J. Jazz Journey

来源:互联网 发布:mac终端打开文件 编辑:程序博客网 时间:2024/05/22 10:37

J - Jazz Journey

题意

序列 a1,a2,...,ad 表示需要从 aiai+1 。现在有 m 种不同的飞机票 ak dk tk pk,每种表示从 akdk,若 tk 为 O 表示单程,为 R 表示往返(但仅有先用该票搭乘 akdk 后才可用该票 dkak

要求对给定的序列求所需的最小花费。保证必定有解。

解题思路

首先根据 aiai+1 将行程进行分堆,单独保存进行处理。处理结果应该如下:

序列为: 1 2 3 1 2 1 3 2 4 1
分堆结果:

      (1 -> 2)  正向 正向 反向      (2 -> 3)  正向 反向      (1 -> 3)  反向 正向      (2 -> 4)  正向      (1 -> 4)  反向

根据 m 种机票的信息,对每条路线记录四种价格: 正向往返, 反向往返, 正向单程, 反向单程
若不存在则默认记为 INF 。
其中应注意四种价格部分存在转换关系,应记录其可能的最低价格,例如:选择正向往返可放弃反向的返程。

对同一条路线,暴力计算三种不同方式的购票方案即可:

  • 只买单程票

  • 优先考虑正向往返票,反向往返票次之,最后单程票

  • 优先考虑反向往返票,正向往返票次之,最后单程票

统计总价格。

代码

#include<bits/stdc++.h>using namespace std;const long long inf = 1ll<< 60;const int D = 300000 + 10;int n, d, m, a[D], mpidx = 0;char tk;vector<bool> trip[D];long long price[D][4];map<pair<int, int>, int> mp;pair<int, int> p;int main(){    scanf("%d %d", &n, &d);    for(int i=1;i<=d;i++)        scanf("%d", &a[i]);    for(int i=1;i<d;i++)    {        if(a[i] > a[i+1])   p = make_pair(a[i+1], a[i]);        else    p = make_pair(a[i], a[i+1]);        if(mp.find(p) == mp.end())            mp[p] = ++mpidx;        trip[mp[p]].push_back(a[i]<a[i+1]?true:false);    }    for(int i=1;i<=mpidx;i++)        for(int j=0;j<4;j++)            price[i][j] = inf;    scanf("%d", &m);    for(int i=1, sk, dk, pk, pos=0, midx;i<=m;i++,pos=0)    {        scanf("%d %d %c %d", &sk, &dk, &tk, &pk);        if(tk == 'O')   pos+=2;        if(sk > dk) p = make_pair(dk, sk),  pos++;        else    p = make_pair(sk, dk);        if(mp.find(p) == mp.end())  continue;        midx = mp[p];        price[midx][pos] = min(price[midx][pos], (long long)pk);    }    long long ans = 0;    for(int i=1;i<=mpidx;i++)    {        if(price[i][0] < price[i][2])   price[i][2] = price[i][0];        if(price[i][1] < price[i][3])   price[i][3] = price[i][1];        if(price[i][2]+price[i][3] < price[i][0])  price[i][0] = price[i][2]+price[i][3];        if(price[i][2]+price[i][3] < price[i][1])  price[i][1] = price[i][2]+price[i][3];        long long tmp[3] = {0, 0, 0};        // 全部单程        for(int j=0;j<trip[i].size();j++)        {            tmp[0] += price[i][3-trip[i][j]];            if(tmp[0] >= inf) {                tmp[0] = inf;   break;            }        }        // 优先 正向往返        if(price[i][0] == inf)  tmp[1] = inf;        else {            deque<bool> que;            for(int j=0;j<trip[i].size();j++)            {                if(trip[i][j] == true)                    que.push_back(true);                else {                    if(!que.empty() && que.back() == true)                        que.pop_back(), tmp[1] += price[i][0];                    else    que.push_back(false);                }            }            int cntTrue = 0, cntFalse = 0;            while(!que.empty()) cntTrue += que.front(), cntFalse += que.front()?false:true,   que.pop_front();            if(price[i][2]+price[i][3] > price[i][1]) {                int mx = min(cntTrue, cntFalse);                tmp[1] += mx * price[i][1];                cntTrue -= mx,  cntFalse -= mx;            }            tmp[1] += price[i][2] * cntTrue + price[i][3] * cntFalse;        }        // 优先 反向往返        if(price[i][1] == inf)  tmp[2] = inf;        else {            deque<bool> que;            for(int j=0;j<trip[i].size();j++)            {                if(trip[i][j] == false)                    que.push_back(false);                else {                    if(!que.empty() && que.back() == false)                        que.pop_back(), tmp[2] += price[i][1];                    else    que.push_back(true);                }            }            int cntTrue = 0, cntFalse = 0;            while(!que.empty()) cntTrue += que.front(), cntFalse += que.front()?false:true,   que.pop_front();            if(price[i][2]+price[i][3] > price[i][0]) {                int mx = min(cntTrue, cntFalse);                tmp[2] += mx * price[i][0];                cntTrue -= mx,  cntFalse -= mx;            }            tmp[2] += price[i][2] * cntTrue + price[i][3] * cntFalse;        }        sort(tmp, tmp+3);        ans += tmp[0];    }    printf("%I64d\n", ans);}
原创粉丝点击