买礼物(洛谷P1194)

题目描述

又到了一年一度的明明生日了,明明想要买 B 样东西,巧的是,这 B 样东西价格都是 A 元。

但是,商店老板说最近有促销活动,也就是:

如果你买了第 I 样东西,再买第 J 样,那么就可以只花 KI,J​ 元,更巧的是,KI,J​ 竟然等于 KJ,I​。

现在明明想知道,他最少要花多少钱。

输入格式

第一行两个整数,A,B。

接下来 B 行,每行 B 个数,第 I 行第 J 个为 KI,J​。

我们保证 KI,J​=KJ,I​ 并且 KI,I​=0。

特别的,如果 KI,J​=0,那么表示这两样东西之间不会导致优惠。

注意 KI,J​可能大于A。

输出格式

一个整数,为最小要花的钱数。

输入输出样例

输入 #1复制运行

1 1 0

输出 #1复制运行

1

输入 #2复制运行

3 3 0 2 4 2 0 2 4 2 0

输出 #2复制运行

7

说明/提示

样例解释 2。

先买第 2 样东西,花费 3 元,接下来因为优惠,买 1,3 样都只要 2 元,共 7 元。

(同时满足多个“优惠”的时候,聪明的明明当然不会选择用 4 元买剩下那件,而选择用 2 元。)

数据规模

对于 30% 的数据,1≤B≤10。

对于 100% 的数据,1≤B≤500,0≤A,KI,J​≤1000。

2018.7.25新添数据一组

1. 题目背景与分析

问题描述:

明明要买B样东西,每样东西的基础价格是A。商店提供优惠策略:如果你买了第I样东西,再买第 J样,花费只需要K_I,J元。题目给出了一个邻接矩阵表示这些优惠价格。特别地,如果 K_I,J=0 表示没有优惠(除了自己对自己)。即使有优惠,K_I,J 也可能比原价A还要贵。求最小总花费。

核心模型:

乍一看,这似乎是一个复杂的动态规划或者贪心问题。但我们仔细分析:

  1. 我们要“买完所有物品”,相当于遍历所有节点。

  2. 我们要“花费最少”,相当于边的权值和最小。

  3. 物品之间的优惠关系构成了图的边。

这就变成了一个经典的最小生成树问题。

2. 难点与突破口

这道题与普通MST有两个不同点:

  1. 入场券问题:普通的MST假设所有点已经在图里,只需连线。但这道题里,你获得第一个物品(或者断开优惠链条重新购买)需要花费原价A。

  2. 坑点:优惠价K_I,J可能比原价A还贵。聪明的明明当然会选择直接花A元购买,而不是用更贵的优惠。

解决方案:Prim 算法+初始化

通常我们做Prim算法时,dis数组(记录节点到当前生成树集合的最小距离)会初始化为无穷大。

但在本题中,每个物品都有一个保底价格A。

我们可以想象有一个“虚拟源点(商店老板)”,他连接着所有物品,边权都是A。

  • 初始化策略:将dis数组全部初始化为A。这意味着,对于任何物品,我们最坏的情况就是花原价A买下来。

  • 更新策略:在松弛操作时,只有当优惠价g[u][v]小于当前记录的花费dis[v]时,才更新。

3. 算法选择

  • 数据规模:B<=500。

  • 图的类型:题目直接给出了邻接矩阵,这是一个典型的稠密图(边数E约等于N^2)。

在稠密图中,Prim算法的时间复杂度为O(N^2),而Kruskal算法是O(E log E)。

对于N=500,Prim运算量约为2.5*10^5,非常高效。因此,Prim+邻接矩阵是本题的最优解。

4. 完整代码

//这道题就是要求买完所有商品最小花费,本质上是求最小生成树 //买了第I样东西,再买第J样,那么就可以只花 K(I,J)元,更巧的是,K (I,J)竟然等于K(J,I) 其实就是告诉我们边权就是kij,要求买完所有物品钱数最少,但 K(I,J)可能大于A,但明明肯定不会花比a还多的钱去买的 因为给出了邻接矩阵,所以我们用prim+邻接矩阵去做 时间复杂度:O(N^2) #include <iostream> using namespace std; int a,b; int g[510][510];//邻接矩阵 int dis[510];//每个物品购买所需的费用(到集合的距离) long long sum;//总费用(最小生成树长度) const int inf=0x3f3f3f3f; int vis[510];//标记每个物品是否已经购买(加入集合) void prim(){ //p作为找最小dis的标记,需要初始化dis[0]为无穷大 dis[0]=inf; //循环b次 每次找出没有购买且离集合最近的点(花费最小的物品) for(int i=1;i<=b;i++){ int p=0; for(int j=1;j<=b;j++){ //没有购买且价格最低 if(vis[j]==0 && dis[j]<dis[p]) p=j; } //无点可以加入当前生成树(无物品可以购买) if(p==0 || dis[p]==inf) break; vis[p]=1;//否则就标记该点已加入集合(购买) sum+=dis[p];//更新总花费 //用p点去更新所有它的未加入集合的邻接点 //(未购买且有优惠关系的物品)的购买价格 for(int j=1;j<=b;j++){ //如果该物品没有购买且当前购买价格大于优惠后价格 //就更新价格 if(vis[j]==0 && dis[j]>g[p][j]){ dis[j]=g[p][j]; } } } } int main(){ cin>>a>>b; //初始化要买的b样物品费用为a for(int i=1;i<=b;i++) dis[i]=a; //邻接矩阵存图(物品间连续购买所需要花的费用 for(int i=1;i<=b;i++){ for(int j=1;j<=b;j++){ cin>>g[i][j]; //特别的,如果K(I,J)=0,那么表示这两样东西之间不会导致优惠 //没有优惠,就让连续购买的价格(边权)变为无穷大即可 if(g[i][j]==0) g[i][j]=inf; } } prim(); cout<<sum; return 0; }

5. 代码细节

  1. 为什么 dis[i] 初始化为a?

    题目中K_I,J可能大于A。如果我们在Prim过程中只比较优惠价,可能会选出一条很贵的边。

    将dis初始为 a,相当于默认所有点都连向了一个“超级源点”,权值为A。在后续的松弛操作 if(dis[j] > g[p][j]) 中,如果优惠价g[p][j]比a还要大,条件不成立,我们就保留了a这个更优解。

  2. 关于0的处理

    题目输入中 0 表示两样东西之间没有导致优惠(即不连通),但在邻接矩阵中 0 通常表示距离极短。为了防止 Prim 算法误选这些“死路”,我们需要在输入时特判:if(g[i][j]==0) g[i][j]=inf;。

  3. 时间复杂度

    Prim 算法包含两层循环,外层遍历N个点,内层寻找最小值和松弛操作也是N,总复杂度 O(N^2)。对于N=500的数据,计算量在2.5*10^5左右,完全满足时间限制。

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

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

相关文章

SSAS - 步骤一:通过VS2022新建项目

本文介绍如何通过Visual Studio 2022创建SSAS项目。 打开CMD窗口&#xff0c;输入如下命令。注意替换服务器地址和VS2022文件的目录。 runas /netonly /user:192.168.88.74\administrator "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\devenv.…

Springboot中使用activemq

1. 引入ActiveMQ的SpringBoot插件<!-- ActiveMQ --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-activemq</artifactId></dependency>2. application中增加activemq的配置spring:acti…

公路修建(洛谷P1265)

题目描述某国有 n 个城市&#xff0c;它们互相之间没有公路相通&#xff0c;因此交通十分不便。为解决这一“行路难”的问题&#xff0c;政府决定修建公路。修建公路的任务由各城市共同完成。修建工程分若干轮完成。在每一轮中&#xff0c;每个城市选择一个与它最近的城市&…

程序监控与异常防护-PART-Simulink-看门狗

程序监控与异常防护-PART-Simulink-看门狗程序监控与异常防护-PART-Simulink-看门狗 关键词 看门狗、程序监控、异常处理、Simulink、自动化控制一、问题分析:为什么需要看门狗 在自动化实验控制平台中,我们经常会遇…

LIDA 477 编码器位移/速度/加速度采集与转换-PART-LIDA 477-采集转换

LIDA 477 编码器位移/速度/加速度采集与转换-PART-LIDA 477-采集转换LIDA 477 编码器位移/速度/加速度采集与转换-PART-LIDA 477-采集转换 关键字:LIDA 477、Hidenhain、磁姗尺、编码器、位移、速度、加速度、Simulin…

1121

编程练习

软件升级回退报告

一、引言为提升软件系统性能、优化现有功能并修复已知问题&#xff0c;本团队于[升级实施日期]对[软件名称]系统开展了版本升级工作&#xff0c;计划将系统从[原版本号]升级至[目标版本号]。升级后&#xff0c;系统出现[简要说明核心问题&#xff0c;如&#xff1a;关键功能异常…

SQL Server数据库

数据库按照特定的数据结构来组织、存储和管理数据的集合作用高效地存储大量数据&#xff0c;并支持快速的查询、修改、删除等操作同时保证数据的安全性、完整性和一致性。一&#xff0c;创建主数据文件命令创建&#xff1a;create 修改&#xff1a;alt…

1124

编程练习

灵活用工系统开发全流程与案例分享【弹性用工解决方案|附源码】

一、模块设计分包商&#xff1a;税地注册公司&#xff0c;用于在当地申请有利的税收政策&#xff0c;是实际报税公司。 代理商&#xff1a;代理商可以邀请客户使用本平台&#xff0c;平台会给予代理商一定的服务费差价作为佣金。 客户&#xff1a;使用本平台进行工资发放的…

RocksDB 可直接运行的实战示例(多语言 + 完整安装 + 基础 CRUD + 事务 + 生产调优)

包含 C++(原生最优)、Java (企业级主流)、Python (快速上手) 三种最常用语言的完整代码,所有示例复制即可运行,涵盖你需要的「安装步骤、基础读写、事务操作、生产级调优参数」,优先级从高到低排序,按需选择即可。 核心前提:RocksDB 是嵌入式键值库,所有操作都是本地库调…

7月4日

今天:完成PTA部分练习,看了看大道至简,看了37页,明白原来完成一个项目是很难的,需要团队合作,就跟建筑一样,需要共同搭配合作,才能建造起来“房子” 明天:学习JAVA基础

VideoDownloadHelper视频下载助手终极指南:全网视频轻松保存

VideoDownloadHelper视频下载助手终极指南&#xff1a;全网视频轻松保存 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 想要将网页中的精彩视…

专业陪诊系统:守护银发健康

博主介绍&#xff1a; 所有项目都配有从入门到精通的安装教程&#xff0c;可二开&#xff0c;提供核心代码讲解&#xff0c;项目指导。 项目配有对应开发文档、解析等 项目都录了发布和功能操作演示视频&#xff1b; 项目的界面和功能都可以定制&#xff0c;包安装运行&#xf…

1126

编程练习

1013

JAVA练习,学习连接数据库

RocksDB 全面指南

RocksDB 是由 Meta&#xff08;原 Facebook&#xff09;开发的高性能嵌入式键值存储引擎&#xff0c;基于 Google LevelDB 改进而来&#xff0c;专为高吞吐量、低延迟的存储场景设计。它是一个 C 库而非独立数据库服务&#xff0c;可嵌入应用程序中提供持久化键值存储能力。一、…

7月5日

今天:完成10道编程题 明天:继续完成假期任务