• Wannafly camp Day1 E Growth


    题意

      二维坐标点(a, b),初始为0,每个时刻可以让a+1或b+1,。当a>=xi且b>=yi时,之后的每个时刻可以获得zi分。

      问m时刻后的最大分数。

      n <= 1000, m <= 2e9, x,y <= 1e9, z <= 1e6

    题解

      考虑到有影响的x和y值只有给定的那些值,所以将x和y分别排序,用t[i][j]表示当a = xi, b = yi时能获得的奖励(对于有多组相同的x和y,对z求和),用v[i][j]表示当a = xi, b = yi时接下来每天能获得的奖励,即t[i][j]的二维前缀和。

      考虑DP,f[i][j]可以从i - 1, j和i, j - 1转移过来,方程为:f[i][j] = max(f[i - 1][j] + (x[i] - x[i - 1] - 1) * v[i - 1][j] + v[i][j], f[i][j - 1] + (y[j] - y[j - 1] - 1) * v[i][j - 1] + v[i][j])

      最后注意扫描找值时要加上剩下天数的贡献。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 int x[1010], y[1010], xx[1010], yy[1010], z[1010];
     5 
     6 map<pair<int, int > , int> h;
     7 
     8 long long t[1010][1010], v[1010][1010];
     9 __int128 f[1010][1010];
    10 
    11 void print(__int128 x)
    12 {
    13     if (x>9) print(x/10);
    14     putchar('0'+x%10);
    15 }
    16 
    17 int main()
    18 {
    19     int n, m;
    20     scanf("%d%d", &n, &m);
    21     for (int i = 1; i <= n; ++i)
    22     {
    23         scanf("%d%d%d", &xx[i], &yy[i], &z[i]);
    24         if (h[{xx[i], yy[i]}])
    25             h[{xx[i], yy[i]}] += z[i];
    26         else
    27             h[{xx[i], yy[i]}] = z[i];
    28     }
    29     sort(xx + 1, xx + n + 1);
    30     sort(yy + 1, yy + n + 1);
    31     int X(0), Y(0);
    32     x[++X] = xx[1];
    33     y[++Y] = yy[1];
    34     for (int i = 2; i <= n; ++i)
    35     {
    36         if (xx[i] != xx[i - 1])
    37             x[++X] = xx[i];
    38         if (yy[i] != yy[i - 1])
    39             y[++Y] = yy[i];
    40     }
    41     for (int i = 1; i <= X; ++i)
    42         for (int j = 1; j <= Y; ++j)
    43             t[i][j] = h[{x[i], y[j]}];
    44     for (int i = 1; i <= X; ++i)
    45         for (int j = 1; j <= Y; ++j)
    46             v[i][j] = v[i - 1][j] + v[i][j - 1] - v[i - 1][j - 1] + t[i][j];
    47     for (int i = 1; i <= X; ++i)
    48         for (int j = 1; j <= Y; ++j)
    49             f[i][j] = max(f[i - 1][j] + (__int128)(x[i] - x[i - 1] - 1) * v[i - 1][j] + v[i][j], f[i][j - 1] + (__int128)(y[j] - y[j - 1] - 1) * v[i][j - 1] + v[i][j]);
    50     __int128 ans(0);
    51     for (int i = 1; i <= X; ++i)
    52         for (int j = 1; j <= Y; ++j)
    53             if (x[i] + y[j] <= m)
    54                 ans = max(ans, f[i][j] + v[i][j] * (m - x[i] - y[j]));
    55     print(ans);
    56     putchar('
    ');
    57 
    58     return 0;
    59 }
  • 相关阅读:
    将博客搬至CSDN
    js进制转换
    js千分位转换
    css让div水平垂直居中
    NPM与调试工具的使用
    Windows下Node.js开发环境搭建-合适的开发环境
    Node.js开发环境介绍-调试工具
    开发环境
    模拟实现call,apply,bind方法,以及三者区别
    观察者模式
  • 原文地址:https://www.cnblogs.com/aseer/p/9473980.html
Copyright © 2020-2023  润新知