HDOJ5616 Jam‘s balance

目录

  • HDOJ5616 Jam's balance
    • 题目描述
      • 背景
      • 输入
      • 输出
    • 题解
      • 解法一
      • 解法二
      • 优化
    • 打赏

HDOJ5616 Jam’s balance

题目描述

背景

N N N个已知质量的砝码,分别询问给出的 M M M个质量能否被称出

输入

  1. 第一行输入一个变量 T T T,表示有 T T T组数据;
  2. 第二行输入一个变量 N N N,表示有 N N N个砝码;
  3. 第三行输入 N N N个变量 w 1 , w 2 , ⋯ , w n w_1, w_2, \cdots, w_n w1,w2,,wn,分别表示这 N N N个砝码的质量;
  4. 第四行输入一个变量 M M M,表示要询问的质量有 M M M个;
  5. 第五行输入 M M M个变量 u 1 , u 2 , ⋯ , u m u_1, u_2, \cdots, u_m u1,u2,,um,分别表示要询问的质量

输出

对于每组数据每个询问的质量判断并输出一行 Y E S YES YES N O NO NO

题解

解法一

定义一个数组 f [ ] f[] f[] f [ i ] f[i] f[i]表示当表示出的质量小于等于 i i i时所能表示的最大值,那么本题就可以看成是一个背包问题,而且是每个物品的体积和价值都一致的背包问题
背包问题的状态转移方程是 f [ j ] = m a x ( f [ j ] , f [ j − v [ i ] ] + w [ i ] ) f[j] = max(f[j], f[j - v[i]] + w[i]) f[j]=max(f[j],f[jv[i]]+w[i]),该问题中即为 f [ j ] = m a x ( f [ j ] , f [ j − w [ i ] ] + w [ i ] ) f[j] = max(f[j], f[j - w[i]] + w[i]) f[j]=max(f[j],f[jw[i]]+w[i]),但是该问题有一些不同,因为砝码可以放在两边,所以不是简单的价值相加,但是考虑用 w [ i ] w[i] w[i]加上前 i − 1 i - 1 i1个砝码组合出的某个方案时还是可以使用这个方程的
现在考虑相减的情况,假设要用第 i i i个砝码更新 f [ j ] f[j] f[j],那么对第 i i i个砝码的使用有两种情况,一是用前 i − 1 i - 1 i1个砝码组合出的某个方案减去 w [ i ] w[i] w[i],二是用 w [ i ] w[i] w[i]减去前 i − 1 i - 1 i1个砝码组合出的某个方案
第一种情况和相加类似,易得 f [ j ] = m a x ( f [ j ] , f [ j + w [ i ] ] − w [ i ] ) f[j] = max(f[j], f[j + w[i]] - w[i]) f[j]=max(f[j],f[j+w[i]]w[i]),但是为了防止 f [ k ] ( k > j ) f[k](k > j) f[k](k>j) f [ j ] f[j] f[j]更先更新,从而导致同一砝码使用两次, j j j应该顺序枚举
第二种情况使用 w [ i ] w[i] w[i]更新时,由于 f [ j ] f[j] f[j]表示的是不大于 j j j的最大值,所以应该用 w [ i ] w[i] w[i]减去不小于 w [ i ] − j w[i] - j w[i]j的最小值,那么还需要再定义一个数组 g [ ] g[] g[] g [ i ] g[i] g[i]表示当表示出的质量大于等于 i i i时所能表示的最小值,于是可以得到方程 f [ j ] = m a x ( f [ j ] , w [ i ] − g [ w [ i ] − j ] ) f[j] = max(f[j], w[i] - g[w[i] - j]) f[j]=max(f[j],w[i]g[w[i]j])
定义了一个新的数组,那么它也需要被维护,方程和 f f f是类似的
接着考虑到实际上只需要判断是否可以得到询问的质量,而不需要真正算出最大值和最小值,所以 f , g f , g f,g都可以换为 b o o l bool bool数组并对方程做出改变
最后考虑相加和两种相减计算的先后顺序,相加第一个,之后无论是何种相减,即使减去的方案中使用了同一砝码也会抵消,第二个是相减的情况二,这样在考虑相减的情况一时遇到同一砝码也会抵消,如果后两者反过来,则会导致统一砝码使用多次
代码如下:

#include<cstdio>
#include<cstring>
using namespace std;const int M = 25;
const int N = 2005;int main() {int t, n, m, mxx, sum;int w[M], v[N];bool f[N], g[N];scanf("%d", &t);while(t--) {memset(f, 0, sizeof(f));memset(g, 0, sizeof(g));g[0] = 0;scanf("%d", &n);for(int i = 1; i <= n; ++i) scanf("%d", &w[i]);scanf("%d", &m);for(int i = 1; i <= m; ++i) scanf("%d", &v[i]);sum = w[1];g[w[1]] = f[w[1]] = g[0] = f[0] = 1;     //初始化不要忘记改了for(int i = 2; i <= n; ++i) {for(int j = sum += w[i]; j > w[i]; --j) {f[j] |= f[j - w[i]];g[j] |= g[j - w[i]];}for(int j = 1; j <= w[i]; ++j) {f[j] |= g[w[i] - j];g[j] |= f[w[i] - j];}for(int j = 1, mx = sum - (w[i] << 1); j <= mx; ++j) {f[j] |= f[j + w[i]];g[j] |= g[j + w[i]];}}for(int i = 1; i <= m; ++i) f[v[i]] ? puts("YES") : puts("NO");}return 0;
}

解法二

接下来考虑是否可以把两种相减变成一种,核心想法还是背包问题的解法
可以考虑把相加和相减分成两个循环,先单纯考虑相加,再用方案减去 w [ i ] w[i] w[i]的方式对方案进行更新,这样就同时考虑了两种相减
代码如下:

#include<cstdio>
#include<cstring>
using namespace std;#define il inlineconst int M = 25;
const int N = 2005;int main() {bool f[N];int t, n, m, sum;int w[M];scanf("%d", &t);while(t--) {memset(f, 0, sizeof(f));sum = 0, f[0] = 1;scanf("%d", &n);for(int i = 1; i <= n; ++i) scanf("%d", &w[i]);for(int i = 1; i <= n; ++i) {for(int j = sum + w[i]; j >= w[i]; --j) f[j] |= f[j - w[i]];sum += w[i];}for(int i = 1; i <= n; ++i) {int mx = sum - w[i];for(int j = 1; j <= mx; ++j) f[j] |= f[j + w[i]];}scanf("%d", &m);while(m--) {int x;scanf("%d", &x);f[x] ? puts("YES") : puts("NO");}}return 0;
}

优化

当同质量的砝码有多个时,如果看成单独的多个砝码,某些本质相同的操作会重复进行,所以不妨看成多重背包再进行二进制优化,二进制优化就是把有多个的某质量砝码依据二进制进行分组等效,如把 8 8 8个质量为 1 1 1的砝码等效质量分别为 1 , 2 , 4 , 1 1 , 2 , 4 , 1 1,2,4,1 4 4 4个砝码,等效前后能表示的质量不变,而砝码数量却下降了
可以发现这个等效本质上就是满 3 3 3 1 1 1,同时两倍质量的砝码数量加 1 1 1,直到不再可以等效
由于可能的砝码数量只有 0 , 1 , 2 0 , 1 , 2 0,1,2,所以不妨使用 b o o l bool bool数组 s s s储存砝码数量, f a l s e , t r u e false , true false,true分别表示 1 , 2 1 , 2 1,2,且 w [ i ] w[i] w[i]表示第 i i i种砝码的质量,再添加一个数组 p o s [ i ] pos[i] pos[i]表示质量为 i i i的砝码在 s s s中的下标,这样每当出现一个新质量的砝码, s s s中元素的总数 t o t tot tot就加 1 1 1
由于数量较小,对于数量为 2 2 2的砝码也可以不采用多重背包的一般方法,直接当成 2 2 2个单独砝码处理即可
代码如下:

#include<cstdio>
#include<cstring>
using namespace std;#define il inlineconst int M = 25;
const int N = 2005;il int read() {int x = 0;char c = getchar();while(c > '9' || c < '0') c = getchar();while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();return x;
}int main() {bool s[M], f[N];int t, n, m, tot, sum, wei;int w[M], pos[N];memset(pos, 0, sizeof(pos));t = read();while(t--) {memset(f, 0, sizeof(f));tot = sum = 0, f[0] = 1;n = read();for(int i = 1, j; i <= n; ++i) {wei = read(), j = pos[wei];while(j && s[j]) s[j] = 0, j = pos[wei <<= 1];if(!j) pos[wei] = ++tot, s[tot] = 0, w[tot] = wei;else s[j] = 1;}for(int i = 1; i <= tot; ++i) {for(int j = sum += w[i]; j >= w[i]; --j) f[j] |= f[j - w[i]];if(s[i]) w[++tot] = w[i], s[tot] = 0;pos[w[i]] = 0;     //顺便重置pos,这样就不用反复memset}for(int i = 1; i <= tot; ++i)for(int j = 1, mx = sum - w[i]; j <= mx; ++j)f[j] |= f[j + w[i]];m = read();while(m--) f[read()] ? puts("YES") : puts("NO");}return 0;
}

打赏

制作不易,若有帮助,欢迎打赏!
赞赏码

支付宝付款码

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

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

相关文章

数据预处理功能教程,上传文件生成知识库 | Chatopera

如何快速的生成高质量的知识库&#xff1f; 数据预处理功能教程 | Chatopera 云服务低代码定制聊天机器人 关于 Chatopera Chatopera 云服务重新定义聊天机器人&#xff0c;https://bot.chatopera.com 定制智能客服、知识库、AI 助手、智慧家居等智能应用&#xff0c;释放创新…

【java算法专场】双指针(上)

目录 前言 基本原理 对撞指针 快慢指针 移动零 算法思路 算法步骤 代码实现 算法分析 复写零 算法思路 算法步骤 代码实现 快乐数 算法思路 算法步骤 代码实现 盛最多水的容器 ​编辑算法思路 代码实现 前言 双指针是一种在数组或链表等线性数据结构中高效…

Unity使用Fmod的线程安全大坑!

对EventInstance设置回调函数时&#xff0c;回调函数内不能调用协程。否则会秒崩溃&#xff0c;并且不带任何报错&#xff01; 协程在主线程中执行&#xff0c;但是事件回调是异步在音频线程中执行的 Event Callbacks 某些 EVENT_CALLBACK_TYPE 回调会在音频线程中执行,比如 …

Axure 教程 | 雅虎新闻焦点

主要内容 在雅虎首页&#xff0c;新闻焦点大图和焦点小图同步切换轮播&#xff0c;本课程我们来学习如何实现这个效果。 交互说明 1.页面载入后&#xff0c;切换当前屏幕显示的5张焦点图&#xff0c;小图标处以横线提示当前焦点图。 2.鼠标移入焦点大图&#xff0c;新闻标题显示…

水平拆分的技巧

水平拆分的原则和技巧 水平拆分是一种常见的数据库优化手段&#xff0c;它涉及到将一个大型表根据特定的字段值拆分成多个较小的表。这种做法可以有效地提高查询效率&#xff0c;尤其是在处理大量数据时。以下是一些关于如何根据业务设计字段进行水平拆分的建议&#xff1a; …

马斯克的SpaceX星舰有多牛?我们离殖民火星还有多远?

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 埃隆马斯克是一位知名的企业家和工程师&#xff0c;他掌握着多家公司&#xff0c;涉及多个领域&#xff0c;包括电动汽车、太空探索、太阳能、脑…

Charles 证书迁移/复制,实现手机安装一次证书可以连接多个设备的 charles 效果

如果你希望在一个手机上安装一次证书&#xff0c;但是使用这个手机可能在不同的时候去连接你自己安装了Charles的不同设备。比如你在公司有有一个电脑&#xff0c;你在家里也有一个电脑&#xff0c;甚至还有一个笔记本等。 如果想实现只给手机安装一次证书&#xff0c;就可以都…

告别数据线!轻松实现iOS和安卓设备间的文件共享

用 AirDroid 的附近传输功能&#xff0c;完全免费&#xff0c;几十个G的文件也可以相互传输。不限制iPhone和iPad数量&#xff0c;多个设备同时登录也不会强迫下线。 当你要在苹果手机和安卓手机之间传输文件&#xff0c;请将AirDroid安装到两台手机上&#xff0c;然后登录同一…

从零开始:STM32与W25Q64 Flash存储器的SPI接口全解析

摘要 本文将从基础出发&#xff0c;全面解析STM32微控制器与W25Q64 Flash存储器通过SPI接口的通信。内容包括SPI基础知识、W25Q64特性、硬件连接、SPI接口配置、读写操作及实际代码示例。 1. SPI通信基础 SPI是一种串行通信协议&#xff0c;主要特点包括&#xff1a; 同步通…

2008-2022年 上市公司-环境绩效数据(EP)

环境绩效&#xff08;Environmental Performance&#xff0c;简称EP&#xff09;是衡量组织在环境管理方面成效的重要指标&#xff0c;它体现了组织如何通过有效的环境管理体系来控制环境因素&#xff0c;实现环境方针和目标。以下是对上市公司环境绩效数据的详细介绍&#xff…

图的拓扑排序

图的拓扑排序&#xff08;Topological Sorting&#xff09;是一种线性排序&#xff0c;用于有向无环图&#xff08;Directed Acyclic Graph&#xff0c;DAG&#xff09;。拓扑排序将图中的顶点排成一个线性序列&#xff0c;使得对于每一条有向边 (u, v)&#xff0c;顶点 u 都排…

安全继电器的使用和工作原理

安全继电器的使用和工作原理 安全继电器是一种用于保护人员和设备安全的电气装置&#xff0c;通常用于监控和控制危险或紧急情况下的电气系统。它的主要作用是在检测到故障或危险情况时迅速切断电路&#xff0c;以防止潜在的伤害或损坏。使用 安全继电器通常用于以下情况&…

[AI开发配环境]VSCode远程连接ssh服务器

文章目录 总览&#xff1a;ssh连接远程服务器连接免密登录&#xff1a;Docker&#xff1a;ssh连接远程宿主机后&#xff0c;进一步连接并使用其中的docker容器reload window 配置解释器&#xff1a;CtrlP&#xff0c;在上面输入“>python”, 然后选selecet interpreter运行命…

Ubuntu磁盘分区和挂载 虚拟机扩容 逻辑卷的创建和扩容保姆及教程

目录 1、VMware虚拟机Ubuntu20.04系统磁盘扩容 2、Linux的磁盘分区和挂载 3、创建逻辑卷和逻辑卷的扩容 1、VMware虚拟机Ubuntu20.04系统磁盘扩容 通过下图可以看出我们的根磁盘一共有20G的大小&#xff0c;现在我们把它扩容为30G 注&#xff1a;如果你的虚拟机有快照是无…

Python高级编程:自然语言处理基础

Python高级编程:自然语言处理基础 在前几篇文章中,我们探讨了Python的基础语法、面向对象编程、标准库、第三方库、并发编程、异步编程、网络编程与网络爬虫、数据库操作与ORM、数据分析与数据可视化、机器学习基础以及深度学习基础。在这篇文章中,我们将深入探讨Python在自…

使用不同环境的配置文件active profile

在 IntelliJ IDEA 的 Run/Debug Configurations 中&#xff0c;Active profiles 选项通常用于与 Spring Boot 应用程序相关的配置。这是 Spring Boot 特有的一个用来管理不同环境配置的特性&#xff0c;通常用来在开发&#xff08;dev&#xff09;、测试&#xff08;test&#…

Springboot基于Redis的高性能分布式缓存数据库的实现与实例

一、引言 在现代的分布式系统和高并发应用中&#xff0c;缓存机制显得尤为重要。Redis作为一种开源&#xff08;BSD许可&#xff09;的内存键值存储&#xff0c;因其高性能、丰富的数据结构和多样化的应用场景&#xff0c;成为开发者们的首选。在这篇博客中&#xff0c;我们将…

CV每日论文--2024.6.26

1、StableNormal: Reducing Diffusion Variance for Stable and Sharp Normal 中文标题&#xff1a;StableNormal&#xff1a;减少扩散方差以实现稳定且锐利的法线 简介&#xff1a;本文介绍了一种创新解决方案&#xff0c;旨在优化单目彩色输入&#xff08;包括静态图片与动态…

最新自助下单彩虹云商城系统源码,含小储云商城模板免授权

最新彩虹商城源码,含小储云商城模板免授权&#xff0c;试用了一下还行&#xff0c;具体的大家可以看看 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/89405387 更多资源下载&#xff1a;关注我。

通过混合栅极技术改善p-GaN功率HEMTs的ESD性能

来源&#xff1a;Improved Gate ESD Behaviors of p-GaN PowerHEMTs by Hybrid Gate Technology&#xff08;ISPSD 24年&#xff09; 摘要 本工作中&#xff0c;首次证明了混合栅极技术在不增加额外面积和寄生效应的前提下&#xff0c;能有效提升p-GaN HEMTs的栅极静电放电(E…