洛谷P1282 多米诺骨牌 【dp】
参考:
https://blog.csdn.net/qq_51354600/article/details/120623720
题意
给定个多米诺骨牌,每个多米诺骨牌由上下两部分组成,每部分的点数为中的某一个数且已给定。
记上下行点数之差为上部分的点数之和-下部分的点数之和。
每一个多米诺骨牌可以执行操作使得上下交换,求最小交换次数使得上下行点数最小
题解
求最小点数的最小交换次数->求每个点数下的最小交换次数
令表示前个多米诺骨牌,上部分的点数和为下的最小交换次数。假设为上下两部分的点数总和,那么点数之差可以表示为。
预处理每个下的最小交换次数,类似背包问题,要么选择上部分点数以加入,要么交换一次以加入下部分点数。
枚举每个,优先更新最小的点数差,如果点数差相等则更新最小交换次数。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
const int maxn = 1000 + 10;
const int inf = 0x3f3f3f3f;
int n;
int sum;
int a[maxn], b[maxn];
int dp[maxn][6 * maxn];
int res = 0, minus = inf;
signed main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a[i], &b[i]);
sum += a[i] + b[i];
}
memset(dp, inf, sizeof(dp));
dp[0][0] = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= 6 * i; j++) {
if (j >= a[i]) dp[i][j] = std::min(dp[i][j], dp[i - 1][j - a[i]]);
if (j >= b[i]) dp[i][j] = std::min(dp[i][j], dp[i - 1][j - b[i]] + 1);
}
for (int i = n; i <= 6 * n; i++) {
int temp = abs(i - (sum - i));
if (temp < minus) {
minus = temp;//更新最小差值
res = dp[n][i];
} else if (temp == minus) res = std::min(res, dp[n][i]);
}
printf("%d", res);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!