首页 > 其他分享 >AtCoder-abc265_e Manhattan Cafe

AtCoder-abc265_e Manhattan Cafe

时间:2022-08-23 23:57:55浏览次数:148  
标签:AtCoder int ll dig 转移 abc265 maxn Manhattan dp

Manhattan Cafe

dp 前缀和优化

很容易想到 \(dp\) 的状态

\(dp[i][j][k]\) 表示前 \(i\) 个点,\(r_x\) 与 \(p_x\) 的差值和为 \(j\),\(r_x\) 与 \(q_x\) 的差值和为 \(k\)

这样的话直接枚举第 \(i\) 组点中,我们取的点的位置,能够做到 \(O(D)\) 的复杂度转移

总的时间复杂度为 \(O(nD^3)\),显然超时

考虑转移的时间进行优化,我们会发现选取的位置不同,会有不同的规律,假设 \(p_i = 1\),\(q_i = 4\)

如果选取的点 \(r_i\) 在 \([1, 4]\),那么 \(|p_i-x_i|+|q_i-x_i| = |p_i - q_i|\),也就是 \(dp[i][j][k] = \sum dp[i-1][j-x][k-y],\) \(x+y=|p_i - q_i|\),此时一定是从一个 \(j'+k'\) 为定值的之前的状态转移过来,这个定值就是 \(j+k-|p_i-q_i|\)

如果选取的点在 \([1, 4]\) 之外,那么与上一个转移相反,这种是从满足 \(j'-k'\) 为定值的状态转移过来,这个定值就是 \(|p_i-q_i|\)

上述转移文字可能不清楚,可以自己列表格,对每个离散点判断一下他应该从什么状态转移过来,就可以理解

因此考虑做两个对角线前缀和,每次 \(O(1)\) 转移

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 1e3 + 10;
typedef long long ll;
const ll mod = 998244353;
ll dp[maxn][maxn], dig[maxn][maxn], a_dig[maxn][maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, d;
    cin >> n >> d;
    vector<int>q(n), p(n);
    for(int i=0; i<n; i++) cin >> q[i];
    for(int i=0; i<n; i++) cin >> p[i]; 
    dp[0][0] = 1;
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<=d; j++)
        {
            for(int k=0; k<=d; k++)
            {
                dig[j][k] = a_dig[j][k] = dp[j][k];
                if(j && k < d)
                    dig[j][k] += dig[j - 1][k + 1];
                if(j && k)
                    a_dig[j][k] += a_dig[j - 1][k - 1];
            }
        }
        for(int j=0; j<=d; j++)
        {
            for(int k=0; k<=d; k++)
            {
                int s = abs(p[i] - q[i]);
                dp[j][k] = 0;
                if(k + j >= s)
                {
                    int l = max(0, j - s), r = k + j - s - max(0, k - s);
                    if(l == 0) dp[j][k] += dig[r][k - s + j - r];
                    else dp[j][k] += dig[r][k - s + j - r] - dig[l - 1][k - s - l + j + 1];
                }
                if(k > s && j)
                    dp[j][k] += a_dig[j - 1][k - 1 - s];
                if(j > s && k)
                    dp[j][k] += a_dig[j - 1 - s][k - 1];
                dp[j][k] %= mod;
            }
        }
    }
    ll ans = 0;
    for(int i=0; i<=d; i++)
        for(int j=0; j<=d; j++)
            ans += dp[i][j];
    cout << ans % mod << endl;
    return 0;
}

标签:AtCoder,int,ll,dig,转移,abc265,maxn,Manhattan,dp
From: https://www.cnblogs.com/dgsvygd/p/16618302.html

相关文章

  • AtCoder Beginner Contest 263(Java)
    A题桶排序1importjava.util.*;2publicclassMain{3publicstaticvoidmain(String[]args){4Scannersc=newScanner(System.in);5......
  • AtCoder Beginner Contest 265 D Iroha and Haiku (New ABC Edition)
    \(O{(n\logn)}\)做法我在考场上只想到此做法,不难想到,可以将三段用二分预处理。\(xs[i]\)表示从\(a_i\)开始总和为\(P\)的末尾编号,可以用二分处理。最后\(O(n)\)判......
  • AtCoder-abc265_e Warp
    Warpdp状态优化一开始想到的状态为:\(dp[i][x][y]\),第\(i\)步走到\((x,y)\)的方案数,但是发现状态转移非常难写,原因是坐标计算非常大后来可以优化一下\(dp\)的状态......
  • ABC265E Warp
    题意Takahashi在二维平面的原点,它可以瞬移\(N\)次,每次可以从当前点\((x,y)\)瞬移至\((x+A,y+B)\),\((x+C,y+D)\),\((x+E,y+F)\)中的任一点.平面上有\(M\)个障碍点不能到......
  • AtCoder Grand Contest 058 部分题目不简要题解
    从这里开始比赛目录ProblemA MakeitZigzag考虑使$1,3,5,7,\cdots,2n-3$这些位置后三个中的最大值在中间,最后再处理一下最后两个位置就行了。Cod......
  • AtCoder-arc146_b Plus and AND
    PlusandAND贪心从高位开始判断,判断每个数字当前位如果置为\(1\)需要多少步,如果当前位原本就是\(1\),则不消耗,如果原本不是,则消耗低位后,需要将低位全部置\(0\)然后......
  • Atcoder ABC 265DEF
    D题目大意给定一个序列\(A=(A_0,\cdot,A_{N-1})\),判断是否能找到一个四元组\((x,y,z,w)\)满足:\(0\lex<y<z<w\leN\)\(\sum_{i=x}^{y-1}A_i=P\)......
  • AtCoder Beginner Contest 265赛后总结
    生日打了场AtcoderBeginner还可以吧……做出了前四道题,第五、六题是dp方程没想出来QwQA-Apple水题+1,感谢atcoder把坑都亮出来QwQ……分两种情况讨论:三个一卖的比(一个......
  • AtCoder Beginner Contest 264(D-E)
    D-"redocta".swap(i,i+1)题意:给一个字符串,每次交换相邻两个字符,问最少多少次变成"atcoder"题解:从左到右依次模拟#include<bits/stdc++.h>usingnamespacestd;......
  • [题解] Atcoder Regular Contest ARC 146 A B C D 题解
    点我看题A-ThreeCards先把所有数按位数从多到少排序,答案的位数一定等于位数最多的三个数的位数之和\(tot\)。对于每个i,把有i位的数排序,并记录每个i的排序结果。最后......