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算法专场】双指针(上)

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

Axure 教程 | 雅虎新闻焦点

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

马斯克的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;然后登录同一…

[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;如果你的虚拟机有快照是无…

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…

2024广东省职业技能大赛云计算赛项实战——构建CICD

构建CI/CD 前言 题目如下&#xff1a; 构建CI/CD 编写流水线脚本.gitlab-ci.yml触发自动构建&#xff0c;具体要求如下&#xff1a; &#xff08;1&#xff09;基于镜像maven:3.6-jdk-8构建项目的drone分支&#xff1b; &#xff08;2&#xff09;构建镜像的名称&#xff1a…

浅浅谈谈如何利用Javase+多线程+计算机网络的知识做一个爬CSDN阅读量总访问量的程序

目录 我们发现csdn的文章 首先为了印证我们的想法 我们用postman往csdn我们任意一篇文章发起post请求 发送请求 ​编辑获得响应结果 我们发现我们的阅读量上涨 PostRequestSender类 但是我们经过测试发现 定义一个字符串数组 把URL放进去 然后延迟启动 在线程池里面…

SaaS架构Client/Server应用的实验室LIS系统源码,服务可拆分,功能易扩展

LIS系统&#xff0c;即实验室&#xff08;检验科&#xff09;信息系统&#xff0c;它是医院信息管理的重要组成部分之一&#xff0c;LIS系统采用了智能辅助功能来处理大信息量的检验工作&#xff0c;即LIS系统不仅是自动接收检验数据&#xff0c;打印检验报告&#xff0c;系统保…

Jboss通过未授权/弱口令进入后台上传webshell

目录 Jboss介绍 CVE-2007-1036 漏洞产生的原因 利用原理 访问页面 写入webshell 未授权访问后上传webshell 这一篇学习通过参考大佬的好文章学习Jboss的弱口令/未授权漏洞进入后台Getshell Jboss介绍 JBoss是一个基于J2EE的开放源代码应用服务器&#xff0c;代码遵循L…

《梦醒蝶飞:释放Excel函数与公式的力量》6.2 TIME函数

6.2 TIME函数 1&#xff09; TIME函数概述 TIME函数是Excel中用于根据指定的小时、分钟和秒返回时间值的内置函数。这个时间值是一个从0&#xff08;12:00 AM&#xff09;开始的序列数&#xff0c;其中一天的每个小时等于1/24&#xff0c;每分钟等于1/(24*60)&#xff0c;每秒…

【系统架构设计师】六、信息系统基础知识(电子政务|企业信息化|电子商务|信息化战略体系)

目录 一、电子政务EG 1.1 电子政务的内容 1.2 电子政务的主要特征 二、企业信息化EI 2.1 企业信息化实现 2.2 企业信息化方法 三、电子商务EC 四、信息化战略体系 五、客户关系CRM 5.1 CRM的功能 5.2 CRM解决方案具备的要素 5.3 CRM的实现过程 六、供应链管理SCM 七…

Flutter TIM 项目实现

目录 1. 服务端API 1.1 生成签名 1.1.1 步骤 第一步:获取签名算法 第二步:查看函数输入输出 第三步:nodejs 实现功能 1.1.2 验证签名 小结 1.2 Rest API 调用 1.2.1 签名介绍 1.2.2 腾讯接口 生成管理员 administrator 签名 包装一个 post 请求函数 查询账号 …

2734. 执行子串操作后的字典序最小字符串(Rust单百算法)

题目 给你一个仅由小写英文字母组成的字符串 s 。在一步操作中&#xff0c;你可以完成以下行为&#xff1a; 选择 s 的任一非空子字符串&#xff0c;可能是整个字符串&#xff0c;接着将字符串中的每一个字符替换为英文字母表中的前一个字符。例如&#xff0c;‘b’ 用 ‘a’…

华为OD机试 - 石头剪刀布游戏(Java 2024 D卷 200分)

华为OD机试 2024D卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;D卷C卷A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测…