2024 (ICPC) Jiangxi Provincial Contest L 题 Campus 题解

简单思路

首先对于所有的出口求一遍最短路,由于出口只会打开并关闭一次,所以大门的开启状态是相当有限的(最多大概30种),我们对于每一种状态直接暴力求答案最后输出即可。

复杂度大概\(O(knlogn)\)

参考代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define endl '\n'
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define rep(i, a, b) for (int i = (a); i < (b); ++i)
#define Forget_that return
#define Just_go 0
#define Endl endl
#define ednl endl
#define eldn endl
#define dnel endl
#define enndl endl
#define Ednl endl
#define Edml endl
#define llmax 9223372036854775807
#define intmax 2147483647

ll n, m, k, T;

struct edge
{
    int to;
    ll value;
    edge(int too, int val)
    {
        to = too;
        value = val;
    }
    bool operator<(const edge &b) const
    {
        return value > b.value;
    }
};

struct point
{
    vector<edge> vec;
} arr[100005];

ll dis[100][100005];
bool isFang[100005];

void dij(int id, int p)   //求每一个出口的最短路
{
    _rep(i, 1, n) isFang[i] = false;

    _rep(i, 1, n) dis[id][i] = intmax;
    dis[id][p] = 0;

    priority_queue<edge> q;
    edge tempaaa(p, 0);
    q.push(tempaaa);

    while (!q.empty())
    {
        edge fir = q.top();
        int now = fir.to;
        q.pop();
        if (isFang[now])
            continue;
        isFang[now] = true;
        for (auto it = arr[now].vec.begin(); it != arr[now].vec.end(); it++)
        {
            if (dis[id][(*it).to] > dis[id][now] + (*it).value)
            {
                dis[id][(*it).to] = dis[id][now] + (*it).value;
                edge t((*it).to, dis[id][(*it).to]);
                q.push(t);
            }
        }
    }
}

ll people[1000006];

struct ChuKou
{
    int p;
    int beg;
    int end;
} chuKou[100];

struct zhuangtai
{
    vector<int> vec;
} timeLcx[1000006];

set<vector<int>> st;
map<vector<int>, ll> mp;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> m >> k >> T;

    for (int i = 1; i <= n; i++)
    {
        cin >> people[i];
    }

    for (int i = 1; i <= k; i++)
    {
        cin >> chuKou[i].p >> chuKou[i].beg >> chuKou[i].end;
    }

    for (int i = 1; i <= m; i++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        arr[u].vec.push_back(edge(v, w));
        arr[v].vec.push_back(edge(u, w));
    }

    for (int t = 1; t <= T; t++)   //记录所有门的状态
    {
        for (int i = 1; i <= k; i++)
        {
            if (t >= chuKou[i].beg && t <= chuKou[i].end)   //如果开启记录1
                timeLcx[t].vec.push_back(1);
            else
                timeLcx[t].vec.push_back(0);      //如果开启记录0
        }
        st.insert(timeLcx[t].vec);
    }

    for (int i = 1; i <= k; i++)          //求所有出口的最短路
    {
        dij(i, chuKou[i].p);
    }

    for (auto it = st.begin(); it != st.end(); it++)    //对于所有情况求最答案
    {
        vector<int> temp;
        for (int i = 0; i < (int)it->size(); i++)
        {
            if ((*it)[i] == 1)
                temp.push_back(i + 1);
        }

        if (temp.size() == 0)
        {
            mp[*it] = -1;
            continue;
        }

        ll ansJuli = 0;
        for (int i = 1; i <= n; i++)
        {
            ll minJuli = llmax;
            for (int j = 0; j < (int)temp.size(); j++)
            {
                minJuli = min(dis[temp[j]][i], minJuli);
            }
            ansJuli += people[i] * minJuli;
        }
        mp[*it] = ansJuli;             //答案记录
    }

    for (int t = 1; t <= T; t++)
    {
        cout << mp[timeLcx[t].vec] << endl;
    }

    Forget_that Just_go;
}

posted @ 2025-01-20 23:23  AcidBarium  阅读(106)  评论(0)    收藏  举报