「模拟赛20191019」A 简单DP
题目描述
给一个n×m的网格,每个格子上有一个小写字母。
对于所有从左上角(1,1)到右下角(n,m)只向下或向右走的路径构成的集合,判断是否存在两条走法不同的路径,使得把它们经过的格子上的字母按顺序记下来得到的序列完全相同。
输入
第一行一个整数T表示数据组数,对于每组数据:
第一行两个整数n,m;
接下来n行,每行一个长度为m的字符串表示网格的每一行。
输出
对于每组数据,输出一行Yes或No表示是否存在这样的两条路径。
样例
样例输入
2
2 2
ab
bc
2 2
ab
cd
样例输出
Yes
No
数据范围
对于100%的数据,1≤n,m≤1000,1≤T≤10。
水题,考虑DP,假设目前考虑到第i行,第j列,要是存在这两条路径,那么它们要么都从上方走来,要么都从左边走来,或者一条从上方走来,一条从左边走来。
讨论一下,第一种情况,只要i−1行,j列可以满足就行了;第二种情况,只要i行,j−1列满足就行了;第三种情况,首先要满足Ai−1,j=Ai,j−1,然后发现只要能走到(i−1,j−1)这个点,就一定存在这样的路径(先沿着同一条路走到(i−1,j−1),然后分别经过(i−1,j)和(i,j−1)到达(i,j))。
于是定义fi,j表示前i行,j列是否满足,则fi,j=fi−1,j|fi,j−1|(Ai−1,j=Ai,j−1)。这道题就做完了……
Code:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 1005
char S[N][N];
int n, m, t, f[N][N];
int main()
{
scanf("%d", &t);
for (; t--; )
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%s", S[i] + 1);
memset(f, 0, sizeof(f));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
f[i][j] |= f[i - 1][j] | f[i][j - 1];
if (i > 1 && j > 1)
f[i][j] |= (S[i][j - 1] == S[i - 1][j]);
}
if (f[n][m])
puts("Yes");
else
puts("No");
}
}
作者:ModestStarlight
出处:http://www.cnblogs.com/ModestStarlight/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
分类:
动态规划 - 一般动态规划
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次 .NET某旅行社酒店管理系统 卡死分析
· 长文讲解 MCP 和案例实战
· Hangfire Redis 实现秒级定时任务,使用 CQRS 实现动态执行代码
· Android编译时动态插入代码原理与实践
· 解锁.NET 9性能优化黑科技:从内存管理到Web性能的最全指南
· 一天 Star 破万的开源项目「GitHub 热点速览」
· 瞧瞧别人家的日期处理,那叫一个优雅!
· 使用TypeScript开发微信小程序(云开发)-入门篇
· 没几个人需要了解的JDK知识,我却花了3天时间研究
· 定时任务稳定性解决方案-healthchecks监控系统