J. Grammy and Jewelry

Grammy and Jewelry


Grammy and Jewelry

这道题比赛的时候没有时间看,因为太菜了,比赛后三天才有时间看这道题。
这道题说的是给一个无向图,每一个节点都要价值为w的财宝,数量无限,求一个人从1节点出发,每走一条边消耗1个时间单位,需要将财宝带回1节点才算真正获得财宝,这些动作需要在t个时间单位中完成。

这题是一个完全背包+最短路问题,我们可以把时间t看做背包的容量,在途中花费的时间为获得财宝的所占用的时间,所以我们先求出头结点到其他结点的最短路径
代码如下

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 3e3 + 10;
typedef pair<int, int> PII;
int n, m, t, v[N];
int ne[N << 1], e[N << 1], h[N << 1], idx, w[N << 1]; //无向图,数组开大一点
int dist[N << 1];
int f[N];
bool vis[N << 1];

void add(int a, int b)
{
    e[idx] = b, w[idx] = 1, ne[idx] = h[a], h[a] = idx++;
}

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, 1});
    while(!heap.empty())
    {
        PII r = heap.top();
        heap.pop();

        int ver = r.second;
        if(vis[ver]) continue;
        vis[ver] = 1;

        for(int i = h[ver]; i != -1; i = ne[i])
        {
            int j = e[i];
            if(dist[j] > dist[ver] + w[i])
            {
                dist[j] = dist[ver] + w[i];
                heap.push({dist[j], j});
            }

        }
    }
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m >> t; //t相当于完全背包中的体积
    for(int i = 2; i <= n; i++) cin >> v[i]; 
    memset(h, -1, sizeof h);
    while(m--)
    {
        int a, b;
        cin >> a >> b;
        add(a, b);
        add(b, a);
    }
    dijkstra();

    for(int i = 1; i <= n; i++)
    {
        for(int j = dist[i] * 2; j <= t; j++)//dist数组乘以2是因为来到结点还要将财宝放回到头结点,故乘2
        {
            f[j] = max(f[j], f[j - dist[i] * 2] + v[i]);
        }
    }

    for(int i = 1; i <= t; i++)
    cout << f[i] << ((i == t ) ? '\n' : ' ');
    return 0;
}
posted @   Flying_bullet  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示