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

【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://www.xdnf.cn/news/20465.html

相关文章:

  • MySQL集群高可用架构之组复制 (MGR)
  • 校园洒水车cad+三维图+设计说书
  • 金属也有“记忆力”?—聊聊二合一玛哈特矫平机如何“消除”金属的记忆
  • 修复存在坏块或05、C4、C5 S.M.A.R.T错误的硬盘
  • Spring Cloud Alibaba快速入门02-Nacos
  • FRCNet
  • Fab资源快速导入UE
  • Shell 脚本实现系统监控与告警
  • Spring Boot中MyBatis的定义与使用
  • IOC为什么交由spring容器管理?
  • 操作系统研发工作心得体会 - 于复杂性中构建秩序
  • 每日一题(2)
  • MySQL学习记录-索引
  • 携程社招前端面经
  • pthread_detach函数
  • 2025最新超详细FreeRTOS入门教程:第二章 FreeRTOS任务创建
  • 设计一个 AB 测试平台
  • 实例和对象的区别
  • 【目录-单选】鸿蒙HarmonyOS开发者基础
  • 自适应滤波器:Ch4 最小均方(LMS)算法
  • [光学原理与应用-433]:晶体光学 - 晶体光学是研究光在单晶体中传播规律及其伴随现象的分支学科,聚焦于各向异性光学媒质的光学特性
  • 上海“我店”模式:消费增值新玩法及其隐忧
  • 论文阅读:VGGT Visual Geometry Grounded Transformer
  • 【C++】引用的本质与高效应用
  • 【高等数学】第十一章 曲线积分与曲面积分——第三节 格林公式及其应用
  • javascript 国际化方法
  • AI 生成式艺术重塑动漫角色创作:从技术逻辑到多元可能性(一)
  • GPT-5发布:统一智能体时代的开启——从“工具”到“协作者”的范式跃迁
  • 详解MySQL环境变量配置及其在备份中的应用
  • 计算机内存的工作原理