2019 ICPC 银川题解(A)

news2024/11/25 20:31:38

赛时没发挥好6题金尾(rank38),剩下很多能写的题,其中四个dp,傻眼ing

A Girls Band Party(背包)

有点迷惑的题,当时看只要 5 5 5 张牌一下子想到暴力枚举,结果发现是不太能行的,导致浪费很多时间。

题意

n n n 张牌,每张牌有 名称,颜色,价值。再给定 5 5 5 个特殊的牌的名称,和一个特殊的牌的颜色。要求从 n n n 张牌中选出 5 5 5 张名称不同的卡牌,基础分数为 5 5 5 张牌的价值之和 s u m sum sum,在此基础上每多一张牌是特殊颜色最终价值加上 0.2 ∗ s u m 0.2*sum 0.2sum,每多一张特殊名字牌最终价值加上 0.1 ∗ s u m 0.1*sum 0.1sum,最终价值向下取整,求选出的卡牌最大可能的价值。

思路

对于复杂的题目我们先从简单的问题开始考虑。

若是对于该问题只考虑价值之和不考虑附加价值和不能同名的问题是否能解决?就是一个简单的背包,容量为 5 5 5 求最大值的问题。

接下来增加新的信息,若是要求 5 5 5 张牌不能重名如何解决?也很简单,分组背包,同名的牌视作一组,一组内的物品只能选一样的背包问题

再增加新的信息,普通颜色和普通名称对答案没有任何影响,特殊颜色和名称也只有数量对答案有影响,和具体是什么无关。我们是否能在背包时顺便统计特殊颜色和特殊名称?,也很简单,因为只要选出 5 5 5 张牌,将特殊颜色和特殊名称也当做价值的一种算进dp方程,给两个各多开一维维护即可。

到此问题已经顺利解决,给出dp方程: d p [ i ] [ j ] [ k ] [ p ] : dp[i][j][k][p]: dp[i][j][k][p] i i i 张卡牌,选出 j j j 张卡牌, k k k 张是特殊颜色, p p p 张是特殊名字卡牌的 合法方案中的最大基数价值。

具体实现可以看代码,有注释和解析。

#include <bits/stdc++.h>
using namespace std;

#define ll long long

const int N = 1e5 + 10;

int n;

string s[10], color;
map<string, bool> mp;

struct node{
    string d, c;
    int val;
}cd[N];

bool cmp(node& A, node& B){
    return A.d < B.d;
}

int f[N][6][6][6]; // 前 i 张卡牌,选出 j 张卡牌,k 张是特殊颜色,p 张是特殊名字卡牌的 最大基数价值

void cmax(int& a, int b){ a = max(a, b); }
void solve(){
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++){
        cin >> cd[i].d >> cd[i].c >> cd[i].val;
    }

    mp.clear();
    for(int i = 0; i < 5; i ++){
        cin >> s[i];
        mp[s[i]] = 1;
    }
    cin >> color;

    sort(cd + 1, cd + 1 + n, cmp);  // 按名称排序,方便进行类似分组背包的dp
    for(int i = 1; i <= n; i ++){
        for(int j = 0; j < 6; j ++){
            for(int k = 0; k < 6; k ++){
                for(int p = 0; p < 6; p ++) f[i][j][k][p] = 0;
            }
        }
    }

    int last = 0; // 记录最近的上一个不同名的卡牌为止
    for(int i = 1; i <= n; i ++){
        if(cd[i].d != cd[i - 1].d) last = i - 1; 

        int c_v = (cd[i].c == color), s_v = mp.count(cd[i].d); // 这张牌是否是特殊颜色和名称

        for(int j = 0; j <= 5; j ++){
            for(int k = 0; k <= j; k ++){
                for(int p = 0; p <= j; p ++){
                    
                    // 不取这张牌
                    cmax(f[i][j][k][p], f[i - 1][j][k][p]); // 可以从同名的卡牌转移 也可以从不同名的转移

                    // 取这张牌
                    if((j != 0 && f[last][j][k][p] == 0) || j == 5) continue ; // j = 5 时注意不要越界了
                    cmax(f[i][j + 1][k + c_v][p + s_v], f[last][j][k][p] + cd[i].val); // 取这一张牌,那么只能从不同名的卡牌转移
                }
            }
        }
    }
   
    ll ans = 0;
    for(int i = 0; i <= 5; i ++){ // 枚举特殊颜色数量
        for(int j = 0; j <= 5; j ++){ // 枚举特殊名字数量
            double mul = 0.2 * (double)i + 0.1 * (double)j; // 系数
            ans = max(ans, (ll)(mul * (double)f[n][5][i][j]) + f[n][5][i][j]);
        }
    }
    cout << ans << "\n";
}

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

    int t;
    cin >> t;
    while(t --){
        solve();
    }
    return 0;
}

H Delivery Route(最短路+拓扑排序)

题意

给定一个有向图 G G G x x x 条双向边 y y y 条单向边,可能有负边(保证是单向边)但保证走过单向边 u → v u\rightarrow v uv 后一定走不回 u u u,求起点 s s s 到所有点的最短路,如果到不了输出 “NO PATH”.

思路

乍一看仿佛很简单,跑个迪杰斯特拉(后文简称djs)最短路不就行了吗?但是写完准备交的时候就发现有坑,因为djs算法是每次从优先队列取出目前为止到起点最近的点 u u u 进行扩展,但是这样的扩展不一定是最优的,但之前扩展过一次下次再想用该点 u u u 扩展就不行了。
考虑这样一个图: 1 1 1 是起点
在这里插入图片描述

1 → 2 → 4 → 5 1\rightarrow2\rightarrow4\rightarrow5 1245 显然是第一轮扩展,在这几个点取出队列之前队首都不会轮到 3 3 3,因为此时 d i s [ 3 ] = 2 > d i s [ 2 ] = 1 > d i s [ 4 ] = 0 > d i s [ 5 ] = 1 dis[3] = 2 > dis[2] = 1 > dis[4] = 0 > dis[5] = 1 dis[3]=2>dis[2]=1>dis[4]=0>dis[5]=1,因为此时这几个点都已经作为过一次扩展点了,之后就不能再次扩展,但是发现当最后点 3 3 3 进行扩展时, 3 → 4 → 5 3\rightarrow4\rightarrow5 345 会更优秀。

由于题目保证没有负环,我们考虑使用拓扑排序进行优化,先将双向边连接起的连通块用并查集合并,再将单向边连接的这些连通块点集度数 + 1 + 1 +1但要注意若是有单向边 u → v u\rightarrow v uv,且 u u u 点是不可从起点到达的,就不用记录该度数。

接下来就是普通的djs算法 + 拓扑排序了,只有当度数为 0 0 0 时才将一个连通块加入优先队列。具体见代码和注释。

#include <bits/stdc++.h>
using namespace std;

#define ll long long
typedef pair<ll, int> pli;

const int N = 25010;
const ll inf = 1e18;

vector<pair<int, int> > g[N], e[N];

int n, m1, m2, s;

priority_queue<pli, vector<pli>, greater<pli>> q;

ll dis[N];
bool vis[N];

struct DSU {
    std::vector<int> f, siz;
    
    DSU() {}
    DSU(int maxn) {
        init(maxn);
    }
     
    void init(int maxn) {
        f.resize(++ maxn); // 重构容器大小到 n
        std::iota(f.begin(), f.end(), 0); // 批量递增赋值
        // siz.assign(maxn, 1); // 赋值n个1
    }
     
    int find(int x) {
        while (x != f[x]) {
            x = f[x] = f[f[x]];
        }
        return x;
    }
     
    bool same(int x, int y) {
        return find(x) == find(y);
    }
     
    bool merge(int x, int y) {
        x = find(x);
        y = find(y);
        if (x == y) {
            return false;
        }
        f[y] = x;
        return true;
    }
};


DSU dsu;
int d[N];
vector<int> ID[N];
void djs_top(){
    for(int i = 1; i <= n; i ++) dis[i] = inf, vis[i] = 0;
    dis[s] = 0;

    q.push({0, s});
    while(!q.empty()){
        auto [di, u] = q.top(); q.pop();

        if(vis[u]) continue ;
        vis[u] = 1;
        // djs
        for(auto [v, w] : g[u]){
            if(dis[v] > dis[u] + w){
                dis[v] = dis[u] + w;
                q.push({dis[v], v});
            }
        }

        // 拓扑排序
        for(auto [v, w] : e[u]){ // 单向边
            int id = dsu.find(v);
            d[id] --;
            if(dis[v] > dis[u] + w) dis[v] = dis[u] + w;
            ID[id].push_back(v); // 存入连通块
            if(!d[id]){ // 当连通块度数为0,再将所有块内之前出现过的点存入队列
                for(auto x : ID[id]) q.push({dis[x], x});
            }
        }
    }
}

void dfs(int u){
    if(vis[u]) return ;
    vis[u] = 1;
    for(auto [v, w] : g[u]) dfs(v);
    for(auto [v, w] : e[u]) dfs(v);
}

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

    cin >> n >> m1 >> m2 >> s;

    dsu.init(n);
    for(int i = 1; i <= m1; i ++){
        int u, v, w;
        cin >> u >> v >> w;
        dsu.merge(u, v); // 并查集合并
        g[u].push_back({v, w});
        g[v].push_back({u, w});
    }

    for(int i = 1; i <= m2; i ++){
        int u, v, w;
        cin >> u >> v >> w;
        e[u].push_back({v, w});
    }
    dfs(s); // 将不可达的点判除

    for(int i = 1; i <= n; i ++){
        if(!vis[i]) continue ;
        for(auto [v, w] : e[i]) d[dsu.find(v)] ++; // 连通块的度数 ++
    }
    djs_top();

    for(int i = 1; i <= n; i ++){
        if(!vis[i]) cout << "NO PATH\n";
        else cout << dis[i] << "\n";
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1173576.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【漏洞复现】Redis未授权

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、影响版本1.3、漏洞复现环境搭建写入计划任务获取反弹shell利用SSH写公钥&#xff0c;免密登陆利用Redis写WebShell 3、检测未授权访问漏洞检测工具参考 1.1…

《 Hello 算法 》 - 免费开源的数据结构与算法入门教程电子书,包含大量动画、图解,通俗易懂

这本学习算法的电子书应该是我看过这方面最好的书了&#xff0c;代码例子有多种编程语言&#xff0c;JavaScript 也支持。 《 Hello 算法 》&#xff0c;英文名称是 Hello algo&#xff0c;是一本关于编程中数据解构和算法入门的电子书&#xff0c;作者是毕业于上海交通大学的…

零代码复现-TCGA联合GEO免疫基因结合代谢基因生信套路(三)

前面的分析中&#xff0c;整理好的关键基因集表达谱矩阵&#xff0c;接下来就准备分子亚型的相关分析。 六、一致性聚类构建分子亚型 在6.TCGA和GEO差异基因获取和预后数据的整理\TCGA文件中获取文件 准备一个生存数据和表达谱矩阵&#xff0c;这里需要注意的是&#xff0c;…

基于Jenkins实现接口自动化持续集成,学完涨薪5k

一、JOB项目配置 1、添加描述 可选选项可填可不填 2、限制项目的运行节点 节点中要有运行环境所需的配置 节点配置教程&#xff1a;https://blog.csdn.net/YZL40514131/article/details/131504280 3、源码管理 需要将脚本推送到远程仓库中 4、构建触发器 可以选择定时构建…

【爬虫实战】用python爬取微博任意关键词搜索结果、exe文件

项目功能简介&#xff1a; 1.交互式配置&#xff1b; 2.两种任意关键词来源&#xff08;直接输入、本地关键词文件&#xff09;&#xff1b; 3.自动翻页(无限爬取)&#xff1b; 4.指定最大翻页页码&#xff1b; 5.数据保存到csv文件&#xff1b; 6.程序支持打包成exe文件…

Go类型嵌入介绍和使用类型嵌入模拟实现“继承”

Go类型嵌入介绍和使用类型嵌入模拟实现“继承” 文章目录 Go类型嵌入介绍和使用类型嵌入模拟实现“继承”一、独立的自定义类型二、继承三、类型嵌入3.1 什么是类型嵌入 四、接口类型的类型嵌入4.1 接口类型的类型嵌入介绍4.2 一个小案例 五、结构体类型的类型嵌入5.1 结构体类…

视频视觉效果制作After Effects 2023 MacOS中文

After Effects 2023是一款业界领先的动态图形和视觉特效软件。它提供了强大的工具集&#xff0c;帮助用户创建引人入胜的视觉效果、动态图形和电影级特效。新的版本带来了更快的渲染速度、增强的图像处理和优化的工作流程&#xff0c;使用户能够更高效地工作。无论您是在电影、…

Kotlin 进阶函数式编程技巧

Kotlin 进阶函数式编程技巧 Kotlin 简介 软件开发环境不断变化&#xff0c;要求开发人员不仅适应&#xff0c;更要进化。Kotlin 以其简洁的语法和强大的功能迅速成为许多人进化过程中的信赖伙伴。虽然 Kotlin 的初始吸引力可能是它的简洁语法和与 Java 的互操作性&#xff0c…

idea文件比对

idea文件比对 1.项目内的文件比对2.项目间的文件比对3. 剪切板对比4. 版本历史(不同分支和不同commit)对比 1.项目内的文件比对 在项目中选择好需要比对的文件(类)&#xff0c;然后选择Compare Files Mac下的快捷键是Commandd&#xff0c; 这样的比对像是git冲突解决一样 …

Peter算法小课堂—单调子序列

最长上升子序列 dp解法&#xff1a; f[i]表示以i结尾的最长上升子序列的长度 按照倒数第二个选谁分类&#xff1a; 我们先扫描i号元素前的每个元素&#xff08;正向&#xff09;&#xff0c;找出第一个比i号元素小的元素k号。①仍然选i号元素&#xff0c;f[i]。②选k号&…

selenium自动化测试入门 —— cookie 处理

driver.get_cookies() # 获得cookie 信息 driver.get_cookies(name) # 获得对应name的cookie信息 add_cookie(cookie_dict) # 向cookie 添加会话信息 delete_cookie(name) # 删除特定(部分)的cookie delete_all_cookies() # 删除所有cookie 示例&#xff1a; from sel…

2022年电工杯数学建模B题5G网络环境下应急物资配送问题求解全过程论文及程序

2022年电工杯数学建模 B题 5G网络环境下应急物资配送问题 原题再现&#xff1a; 一些重特大突发事件往往会造成道路阻断、损坏、封闭等意想不到的情况&#xff0c;对人们的日常生活会造成一定的影响。为了保证人们的正常生活&#xff0c;将应急物资及时准确地配送到位尤为重要…

MapReduce:大数据处理的范式

一、介绍 在当今的数字时代&#xff0c;生成和收集的数据量正以前所未有的速度增长。这种数据的爆炸式增长催生了大数据领域&#xff0c;传统的数据处理方法往往不足。MapReduce是一个编程模型和相关框架&#xff0c;已成为应对大数据处理挑战的强大解决方案。本文探讨了MapRed…

【深度学习】pytorch——Autograd

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ 深度学习专栏链接&#xff1a; http://t.csdnimg.cn/dscW7 pytorch——Autograd Autograd简介requires_grad计算图没有梯度追踪的张量ensor.data 、tensor.detach()非叶子节点的梯度计算图特点总结 利用Autograd实…

全网最详细的【shell脚本的入门】

&#x1f3c5;我是默&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; ​ &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Linux》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还是有一定基础的程序员&#xff0c;这…

【LearnOpenGL基础入门——2】搭建第一个OpenGL窗口

目录 一.配置GLFW 二.配置GLAD 三.第一个OpenGL窗口 3.1 GLFW设置 3.2 GLAD设置 3.3 视口 3.4 输入 3.5渲染 在我们画出出色的效果之前&#xff0c;首先要做的就是创建一个OpenGL上下文(Context)和一个用于显示的窗口。然而&#xff0c;这些操作在每个系统上都是不一样…

Swift 和 Python 两种语言中带关联信息错误(异常)类型的比较

0. 概览 如果我们分别在平静如水、和谐感人的 Swift 和 Python 社区抛出诸如“Python 是天下最好的语言…” 和 “Swift 是宇宙第一语言…”之类的言论会有怎样的“下场”&#xff1f; 我们并不想对可能发生的“炸裂”景象做出什么预测&#xff0c;也无意比较 Swift 与 Pytho…

[pytorch]手动构建一个神经网络并且训练

0.写在前面 上一篇博客全都是说明类型的,实际代码能不能跑起来两说,谨慎观看.本文中直接使用fashions数据实现softmax的简单训练并且完成结果输出.实现一个预测并且观测到输出结果. 并且更重要的是,在这里对一些训练的过程,数据的形式,以及我们在softmax中主要做什么以及怎么…

14.1 Linux 并发与竞争

一、并发与竞争 并发&#xff1a;多个执行单元同时、并行执行。 竞争&#xff1a;并发的执行单元同时访问共享资源(硬件资源和软件上的全局变量等)易导致竞态。 二、原子操作 1. 原子操作简介 原子操作&#xff1a;不能再进一步分割的操作&#xff0c;一般用于变量或位操作。 …

关于iOS:如何使用SwiftUI调整图片大小?

How to resize Image with SwiftUI? 我在Assets.xcassets中拥有很大的形象。 如何使用SwiftUI调整图像大小以缩小图像&#xff1f; 我试图设置框架&#xff0c;但不起作用&#xff1a; 1 2 Image(room.thumbnailImage) .frame(width: 32.0, height: 32.0) 在Image上应用…