当前位置: 首页 > news >正文

【01背包问题变体】P1282 多米诺骨牌

题目

P1282 多米诺骨牌
在这里插入图片描述

分析

题目分析

目标:通过旋转多米诺骨牌,使上下两行点数之差的绝对值最小,在最小差值的前提下旋转次数最少。

关键信息

  • 每个骨牌可以旋转180°(上下互换)
  • 旋转次数要最少
  • 最终差值要最小

思考过程

第一步:识别问题类型

这是一个双目标优化问题

  1. 主要目标:最小化差值绝对值
  2. 次要目标:在最小差值下最小化旋转次数

第二步:分析决策过程

对于每个多米诺骨牌,我们有两个选择:

  • 不旋转:保持原来的上下关系
  • 旋转:上下互换

第三步:思考状态表示

尝试1:简单的线性状态
f[i] = 前i个骨牌的最小旋转次数

问题:无法表示当前的差值状态,不知道旋转后差值是多少。

尝试2:二维状态
f[i][j] = 前i个骨牌,旋转j次的最小差值

问题:这样设计无法同时优化两个目标。

尝试3:正确的二维状态
f[i][j] = 前i个骨牌,当前差值为j时的最小旋转次数

为什么这样设计?

  • i:处理到第几个骨牌
  • j:当前的差值(可以是负数)
  • 值:达到这个差值需要的最小旋转次数

第四步:分析状态转移

对于第i个骨牌,设其上下点数分别为a[i]b[i]

情况1:不旋转
  • 差值贡献:a[i] - b[i]
  • 如果前i-1个骨牌的差值是j - (a[i] - b[i]),那么加上第i个骨牌后差值变成j
  • 转移:f[i-1][j - (a[i] - b[i])] → f[i][j]
情况2:旋转
  • 差值贡献:b[i] - a[i] = -(a[i] - b[i])
  • 如果前i-1个骨牌的差值是j - (b[i] - a[i]),那么加上第i个骨牌后差值变成j
  • 转移:f[i-1][j - (b[i] - a[i])] + 1 → f[i][j]
简化表示

diff[i] = a[i] - b[i]

  • 不旋转:f[i-1][j - diff[i]] → f[i][j]
  • 旋转:f[i-1][j + diff[i]] + 1 → f[i][j]

第五步:边界条件

f[0][0] = 0  // 0个骨牌,差值为0,旋转次数为0
f[0][j] = INF (j ≠ 0)  // 0个骨牌不可能有非零差值

第六步:答案提取

由于我们要最小化差值的绝对值,应该从差值0开始搜索:

for(int j = 0; j <= max_diff; j++) {if(f[n][j] != INF || f[n][-j] != INF) {return min(f[n][j], f[n][-j]);}
}

关键思考

1. 为什么用差值作为状态维度?

  • 差值直接反映了我们的优化目标
  • 通过记录所有可能的差值,我们可以在最后选择最小的

2. 为什么用旋转次数作为状态值?

  • 旋转次数是我们的次要优化目标
  • 在相同差值下,我们选择旋转次数最少的方案

3. 为什么这样设计能同时优化两个目标?

  • 通过遍历所有可能的差值,我们找到了最小可达差值
  • 对于每个差值,我们记录了达到该差值的最小旋转次数
  • 因此自然实现了"最小差值下的最小旋转次数"

设计思路总结

  1. 识别双目标:最小化差值 + 最小化旋转次数
  2. 确定主次:差值为主,旋转次数为次
  3. 状态设计:用差值作为状态维度,旋转次数作为状态值
  4. 转移分析:考虑每个骨牌的两种选择
  5. 答案提取:从最小差值开始搜索

这种设计思路的核心是:将次要目标作为状态值,将主要目标作为状态维度,这样可以在DP过程中同时优化两个目标。

代码

#include<iostream>
#include<cstring>using namespace std;const int N = 1010, M = 1e4 + 10, INF = 0x3f3f3f3f;int n, a[N], f[N][M];int m = 5000;int main()
{cin >> n;for(int i=1;i<=n;i++){int x,y; cin >> x >> y;a[i] = x - y;}memset(f,0x3f,sizeof f);f[0][0+m] = 0;for(int i=1;i<=n;i++){for(int j=-m;j<=m;j++){f[i][j+m] = min(f[i-1][j-a[i]+m],f[i-1][j+a[i]+m]+1);}}int ret = INF;for(int j=0;j<=m;j++){ret = min(f[n][j+m],f[n][-j+m]);if(ret != INF) break;}cout << ret;return 0;
}

文章转载自:

http://MI0SLzEZ.stwxr.cn
http://xZYhE6SA.stwxr.cn
http://3U8mDI8F.stwxr.cn
http://oLADk91Q.stwxr.cn
http://qzfCAsGo.stwxr.cn
http://e0nV8TN3.stwxr.cn
http://086SjHD5.stwxr.cn
http://67CEJgWX.stwxr.cn
http://IyeorkiW.stwxr.cn
http://EkRFYGyU.stwxr.cn
http://unJYB8eV.stwxr.cn
http://5mNVlgkB.stwxr.cn
http://rF1DwS4G.stwxr.cn
http://19C5gojN.stwxr.cn
http://2OuK2n4n.stwxr.cn
http://GKQ5i2fC.stwxr.cn
http://e10km39O.stwxr.cn
http://5tvwFeP9.stwxr.cn
http://8gM9BlBM.stwxr.cn
http://R1tKRXn9.stwxr.cn
http://qka1qXIT.stwxr.cn
http://DC8vfiWl.stwxr.cn
http://aAdDpx54.stwxr.cn
http://eN0Mw0UI.stwxr.cn
http://lKmnmR8Q.stwxr.cn
http://13qgQvpk.stwxr.cn
http://11Hl7s2M.stwxr.cn
http://AnnFRBT0.stwxr.cn
http://IRMOgNWJ.stwxr.cn
http://TQyLy0d0.stwxr.cn
http://www.dtcms.com/a/369872.html

相关文章:

  • 【C++】类和对象(三)
  • 【面试向】人工智能机器学习介绍
  • 轻量级XML读写库Mini-XML的编译和使用
  • 【数论】P10580 [蓝桥杯 2024 国 A] gcd 与 lcm|普及+
  • 微服务的编程测评系统22-项目部署结束
  • DNS解析中的服务器协作机制
  • Windows权限提升(二)
  • Homebrew执行brew install出现错误(homebrew-bottles)
  • 数据结构之二叉树(1)
  • Vue 3项目中引用ECharts并设计多种图表组件的实现方案
  • Day37 MQTT协议 多客户端服务器模型
  • 【UAV】基于PX4+Ubuntu24.04.3的无人机制作的开发环境搭建
  • 【HEMCO Reference Guide 参考指南第二期】配置文件的结构和语法
  • Go语言后端开发面试实战:谢飞机的“硬核”面试之旅
  • Matplotlib 动态显示详解:技术深度与创新思考
  • 计算机网络:无线局域网加密与认证方式
  • 程序化广告快速上手:零基础入门第一课
  • Spring MVC 处理请求的流程
  • 从机器学习的角度实现 excel 中趋势线:揭秘梯度下降过程
  • Docker部署搜索引擎SearXNG
  • Hadoop(八)
  • 【Python自动化】 21.2 Pandas 读取 Excel 时的 dtype 参数完全指南
  • 【面板数据】各省制造业出口技术复杂度数据集(2010-2023年)
  • 使用 YAML 自动化 Azure DevOps 管道
  • 【数据库相关】TxSQL新增数据库节点步骤
  • 理想汽车智驾方案介绍 4 World model + 强化学习重建自动驾驶交互环境
  • 大语言模型预训练数据采集与清洗技术实践:从语料到知识库的全流程优化
  • 腾讯混元翻译模型Hunyuan-MT-7B开源,先前拿了30个冠军
  • MiniDrive:面向自动驾驶的更高效的视觉语言模型
  • 2025年渗透测试面试题总结-54(题目+回答)