• 【洛谷习题】多米诺骨牌


    题目链接:https://www.luogu.org/problemnew/show/P1282


    花了好长时间终于写出了这道题,主要是状态转移方程比较奇葩,类似于背包问题,难以想到。

    呃呃,写得DP不多,对于如何想出状态转移方程还没什么心得,主要是往之前见过的模型上靠。这道题的话,其实可以稍微转化一下设问,变成有n个数,每次操作可以将其变为相反数,问最少操作几次可以使总和的绝对值最小。设dp[i][j]为考虑到第i个数,总和为j时最少的操作次数。状态转移方程为dp[i][j]=min(dp[i-1][j-num[i]],dp[i-1][j+num[i]]+1)。因为是取最小值,一开始要把dp数组初始化成inf,还要将未进行操作的dp初始化为0。反正代码细节也还是有的。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 
     8 const int maxn = 1e3 + 5, maxm = 1e4 + 5, inf = 0x3f3f3f3f;
     9 
    10 int num[maxn], dp[maxn][maxm], mm[maxn];
    11 
    12 inline int map(int x) {
    13     return x + 5e3 + 1;
    14 }
    15 
    16 int main() {
    17     int n, a, b, sum = 0;
    18     scanf("%d", &n);
    19     for (int i = 1; i <= n; ++i) {
    20         scanf("%d%d", &a, &b);
    21         num[i] = a - b;
    22     }
    23     memset(dp, inf, sizeof(dp));
    24     for (int i = 0; i <= n; ++i) {
    25         dp[i][map(sum)] = 0;
    26         sum += num[i];
    27         mm[i] = mm[i - 1] + abs(num[i]);
    28     }
    29     for (int i = 1; i <= n; ++i)
    30         for (int j = -mm[i]; j <= mm[i]; ++j)
    31             dp[i][map(j)] = min(dp[i - 1][map(j - num[i])], dp[i - 1][map(j + num[i])] + 1);
    32     for (int i = 0; i <= mm[n]; ++i)
    33         if (dp[n][map(i)] != inf || dp[n][map(-i)] != inf) {
    34             printf("%d", min(dp[n][map(i)],dp[n][map(-i)]));
    35             return 0;
    36         }
    37     return 0;
    38 }
    AC代码
  • 相关阅读:
    Leetcode 1. Two Sum (Python)
    视觉机器学习------KNN学习
    anaconda新建虚拟环境安装各个依赖包
    Matconvnet安装
    argparse模块
    Matconvnet笔记(一)
    Ubuntu14.04下如何安装TensorFlow
    springboot2+freemarker简单使用
    mongodb安装4.0(rpm)
    检测web界面不能访问后重启
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9609389.html
Copyright © 2020-2023  润新知