[ABC265F] Manhattan Cafe 题解
1.AT_abc333_e [ABC333E] Takahashi Quest 题解
2.[ABC265F] Manhattan Cafe 题解
3.[ABC271E] Subsequence Path 题解4.[ABC273D] LRUD Instructions 题解5.P8085 [COCI2011-2012#4] KRIPTOGRAM 题解6.[ABC238F] Two Exams 题解7.[ABC217F] Make Pair 题解8.[ABC219F] Cleaning Robot 题解9.[ABC219E] Moat 题解10.[ABC221D] Online games 题解11.[ABC221E] LEQ 题解12.[ABC223E] Placing Rectangles 题解13.[ABC211D] Number of Shortest paths 题解14.[ABC211F] Rectilinear Polygons 题解15.[ABC223F] Parenthesis Checking 题解16.CF154C Double Profiles 题解17.[ABC208D] Shortest Path Queries 2 题解18.[ABC212E] Safety Journey 题解19.[ABC229E] Graph Destruction 题解20.[ABC240E] Ranges on Tree 题解21.[ABC261E] Many Operations 题解22.P10842 【MX-J2-T3】Piggy and Trees 题解[ABC265F] Manhattan Cafe 题解
思路解析
很有思维难度的一道题。思路是dp,
由此图可见我们需要分类讨论在这一维上
- 这里的
代表的是 ,也就是 和 之间的区间长度。
如果你能想到这一步,非常好,你已经获得了一个
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N = 110, D = 1010, mod = 998244353;
ll n, d;
ll p[N], q[N];
ll f[N][2 * D][D], sum[2 * D][D], sum2[2 * D][D];
int main() {
cin >> n >> d;
for(int i = 1; i <= n; i++) {
cin >> p[i];
}
for(int i = 1; i <= n; i++) {
cin >> q[i];
}
f[0][0][0] = 1;
for(int i = 1; i <= n; i++) {
ll s = abs(p[i] - q[i]);
for(int j = 0; j <= 2 * d; j++) {
for(int k = 0; k <= d; k++) {
f[i][j][k] = 0;
for(int l = 0; l <= s; l++) {
if(j - l >= 0 && k - s + l >= 0) {
f[i][j][k] += f[i - 1][j - l][k - s + l];
f[i][j][k] %= mod;
}
}
for(int l = 1; j - l >= 0 && k - s - l >= 0; l++) {
if(j - l >= 0 && k - s - l >= 0) {
f[i][j][k] += f[i - 1][j - l][k - s - l];
f[i][j][k] %= mod;
}
}
for(int l = 1; j - s - l >= 0 && k - l >= 0; l++) {
if(j - s - l >= 0 && k - l >= 0) {
f[i][j][k] += f[i - 1][j - s - l][k - l];
f[i][j][k] %= mod;
}
}
}
}
}
ll ans = 0;
for(ll j = 0; j <= d; j++) {
for(ll k = 0; k <= d; k++) {
if(abs(j - k) <= d) {
ans += f[n][j][k];
ans %= mod;
}
}
}
cout << ans;
return 0;
}
但很遗憾此题数据为
-
对于第一种情况:可见这种情况的对角线是一条垂直于主对角线的对角线,可以用一个
表示 所存在的这条对角线从 一直累加到 的值。但是需要注意我们只选取对角线中结尾为 且长度最长为 ,因为只有这些情况的取值是符合这种情况分类讨论的判断条件的。以及如果对角线的两端小于 ,也就是两端不存在,我们就特判两端是否存在,只统计剩余的存在的部分(我就是因为这里卡了一晚上。 -
对于第二和第三种情况:可见它们所经过的对角线是一条平行于主对角线的对角线,可以用一个
表示从这条对角线的开头累加到 的值。
具体内容见下图:
code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N = 110, D = 1010, mod = 998244353;
ll n, d;
ll p[N], q[N];
ll f[N][2 * D][D], sum[2 * D][2 * D], sum2[2 * D][2 * D];
int main() {
cin >> n >> d;
for(ll i = 1; i <= n; i++) {
cin >> p[i];
}
for(ll i = 1; i <= n; i++) {
cin >> q[i];
}
f[0][0][0] = 1;
for(int i = 1; i <= n; i++) {
memset(sum, 0, sizeof(sum)); //别忘了清空数组
memset(sum2, 0, sizeof(sum2));
for(ll j = 0; j <= d; j++) {
for(ll k = 0; k <= d; k++) {
if(j - 1 >= 0) {
sum[j][k] += sum[j - 1][k + 1];
sum[j][k] %= mod; //记得取模
}
sum[j][k] += f[i - 1][j][k];
sum[j][k] %= mod;
if(j - 1 >= 0 && k - 1 >= 0) {
sum2[j][k] += sum2[j - 1][k - 1];
sum2[j][k] %= mod;
}
sum2[j][k] += f[i - 1][j][k];
sum2[k][k] %= mod;
}
}
ll s = abs(p[i] - q[i]);
for(ll j = 0; j <= d; j++) {
for(ll k = 0; k <= d; k++) {
f[i][j][k] = 0;
if(k - s >= 0) { //细节特判
if(j - s >= 0) {
f[i][j][k] += (sum[j][k - s] - sum[j - s][k] + f[i - 1][j - s][k]) % mod;
}
else {
f[i][j][k] += (sum[j][k - s] - sum[0][k - s + j] + f[i - 1][0][k - s + j]) % mod;
}
}
else {
if(j - s >= 0) {
f[i][j][k] += (sum[j - s + k][0] - sum[j - s][k] + f[i - 1][j - s][k]) % mod;
}
else {
f[i][j][k] += (sum[j - s + k][0] - sum[0][k - s + j] + f[i - 1][0][k - s + j]) % mod;
}
}
f[i][j][k] %= mod;
if(j - 1 >= 0 && k - s - 1 >= 0) {
f[i][j][k] += sum2[j - 1][k - s - 1];
f[i][j][k] %= mod;
}
if(j - s - 1 >= 0 && k - 1 >= 0) {
f[i][j][k] += sum2[j - s - 1][k - 1];
f[i][j][k] %= mod;
}
}
}
}
ll ans = 0;
for(ll j = 0; j <= d; j++) {
for(ll k = 0; k <= d; k++) {
ans += f[n][j][k];
ans %= mod;
}
}
cout << ans;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人