ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ABC265 F - Manhattan Cafe

2022-09-04 18:01:39  阅读:241  来源: 互联网

标签:include 前缀 int ABC265 对角线 Cafe 优化 Manhattan mod


前缀和优化DP

F - Manhattan Cafe (atcoder.jp)

题意

给定 n,d(n <= 100, d <= 1000)

在 n 维空间中, 给定两个点 p,q,求点 r 的数量,满足 r 与 p,q 的曼哈顿距离均 <= d

思路

首先考虑朴素dp,设 \(f[k][i][j]\) 表示考虑前 k 维,r 与 p 的曼哈顿距离为 i,与 q 的曼哈顿距离为 j 的点的数量

对于第 k + 1 维,枚举 r 第 k + 1 维的坐标,进行转移

这样复杂度为 \(O(nd^3)\)

首先考虑优化空间,第一维可以滚动

再考虑优化转移复杂度,朴素的转移复杂度为 \(O(d)\), 但实际上不需要枚举第 k + 1 维每个坐标,这些坐标可以分成两类,记第 i 维 p,q,r 的坐标分别为 \(p_i,q_i,r_i\)

可以分为 \(r_i\) 在 $p_i,q_i $ 中间或两侧

设 \(z=|p-q|\)

  1. \(r_i\) 在中间

image

从 0 到 z 枚举 t,\(f[i][j]+=f[i-t][j-s]\), 因为 t + s == z, 为定值,因此所有的 \(f[i-t][j-s]\) 都在以 \(x+y=i+j-z\) 的副对角线上,用前缀和优化转移即可

  1. \(r_i\) 在两侧

image

同理,\(f[i][j]+=f[i-t][j-s]\), t - s 为定值 z,因此所有的 \(f[i-t][j-s]\) 都在 \(y-x=j-i+z\) 的主对角线上,前缀和优化转移即可

r 在 p 右边同理

每次算完当前的 \(f[i][j]\) 后,要更新两个对角线前缀和矩阵

总结

本题的关键是前缀和优化转移,但前缀和是对角线的形式,比较少见,而且考虑边界问题较多,出现负数时及时特判

优化转移时一定要画图!

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>

using namespace std;
#define endl "\n"

typedef long long ll;
typedef pair<int, int> PII;

const int N = 1e3 + 10, M = 1e2 + 10, mod = 998244353;
int n, d;
int p[M], q[M];
ll f[N][N], C[2][N][N], E[2][N][N];
//C[i][j]表示以(i,j)为终点的主对角线的f的前缀和
//E[i][j]表示以(i,j)为终点的副对角线,从 右上 到 (i,j) 的f的前缀和
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n >> d;
	for (int i = 1; i <= n; i++)
		cin >> p[i];
	for (int i = 1; i <= n; i++)
		cin >> q[i];
	for (int i = 0; i <= d; i++)
		C[0][i][i] = 1;
	E[0][0][0] = 1;
	for (int k = 1; k <= n; k++)
	{
		int a = k & 1, b = a ^ 1;
		int z = abs(p[k] - q[k]);
		for (int i = 0; i <= d; i++)
		{
			for (int j = 0; j <= d; j++)
			{
				f[i][j] = 0;
				//前缀和优化转移
				//这里不能取到端点,因为端点在第二种情况被包括了
				if (i - 1 >= 0 && j - z - 1 >= 0)
					f[i][j] += C[b][i-1][j-z-1];
				if (j - 1 >= 0 && i - z - 1 >= 0)
					f[i][j] += C[b][i-z-1][j-1];
				f[i][j] %= mod;
				if (i + j >= z)
				{
					//找到合法的那一段对角线
					int r = min(i, i + j - z), l = i + j - z - min(j, i + j - z) - 1;
					f[i][j] += E[b][r][i+j-z-r];
					if (l >= 0)
						f[i][j] -= E[b][l][i+j-z-l];
					f[i][j] = (f[i][j] % mod + mod) % mod;
				}

				//更新两个对角线前缀和矩阵
				if (i >= 1 && j >= 1)
					C[a][i][j] = (C[a][i-1][j-1] + f[i][j]) % mod;
				else
					C[a][i][j] = f[i][j];
				if (i >= 1)
					E[a][i][j] = (E[a][i-1][j+1] + f[i][j]) % mod;
				else
					E[a][i][j] = f[i][j];
			}
		}
	}

	ll ans = 0;
	for (int i = 0; i <= d; i++)
		for (int j = 0; j <= d; j++)
			ans = (ans + f[i][j]) % mod;
	cout << ans << endl;
    return 0;
}

标签:include,前缀,int,ABC265,对角线,Cafe,优化,Manhattan,mod
来源: https://www.cnblogs.com/hzy717zsy/p/16655587.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有