CodeForces - 570E - Pig and Palindromes dp

本文介绍了一种利用动态规划算法解决寻找地图上回文串路径数量的问题。通过从起点和终点同时进行搜索,并使用滚动数组优化内存占用,最终实现高效计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

题意:给定一个 n ∗ m n*m nm 的地图,地图上每个格子有一个小写的英文字母,起点为 ( 1 , 1 ) (1,1) (11) ,终点为 ( n , m ) (n,m) (nm) ,且每一步的移动只能往右移一格或者往下移一格。求所有从起点到终点的路径,经过的格子按顺序能组成回文串的路径个数。

思路:由于回文串的对称性,可以考虑同时从起点和终点出发,一个往右或下移动,一个往左或上移动。这样状态则为 ( x 1 , y 1 , x 2 , y 2 ) (x1,y1,x2,y2) (x1y1x2y2) ,但是这样会超出内存限制。
由于是同时移动,所以两个点经过的步数相同,而已知步数和横坐标,就可以求出纵坐标,所以把状态进一步化简得 ( s t e p , x 1 , x 2 ) (step,x1,x2) (stepx1x2) ,但是这样还是会超出内存限制,所以就用滚动数组去掉 s t e p step step 这一维即可,之后便是一般的 d p dp dp 过程。

#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
const int mod = 1e9 + 7;
int n, m;
char a[505][505] = {};
int dp[2][505][505] = {};//表示当前某个状态的方法数
inline void AC()
{
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
    {
        getchar();
        for (int j = 1; j <= m; ++j)
            a[i][j] = getchar();
    }
    if (a[1][1] != a[n][m])
    {
        printf("0");
        return;
    }
    dp[1][1][n] = 1;
    for (int step = 2; step * 2 <= n + m - 1; ++step)
    {
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= n; ++j)
                dp[step % 2][i][j] = 0;
        for (int x1 = 1; x1 <= step && x1 <= n; ++x1)
        {
            int y1 = step - x1 + 1;
            if (y1 < 1 || y1 > m)
                continue;
            for (int x2 = 1; x2 <= step && x2 <= n; ++x2)
            {
                int y2 = step - x2 + 1;
                x2 = n - x2 + 1;
                y2 = m - y2 + 1;
                if (y2 < 1 || y2 > m || a[x1][y1] != a[x2][y2])
                {
                    x2 = n + 1 - x2;
                    continue;
                }
                (dp[step % 2][x1][x2] += dp[1 - step % 2][x1 - 1][x2]) %= mod;
                (dp[step % 2][x1][x2] += dp[1 - step % 2][x1 - 1][x2 + 1]) %= mod;
                (dp[step % 2][x1][x2] += dp[1 - step % 2][x1][x2 + 1]) %= mod;
                (dp[step % 2][x1][x2] += dp[1 - step % 2][x1][x2]) %= mod;
                //printf("step:%d [%d,%d] [%d,%d]\n", step, x1, y1, x2, y2);
                x2 = n + 1 - x2;
            }
        }
    }
    int ans = 0;
    int step = (n + m - 1) >> 1;
    if ((n + m - 1) & 1)
    {
        for (int x = 1; x <= n; ++x)
        {
            (ans += dp[step % 2][x][x + 1]) %= mod;
            (ans += dp[step % 2][x - 1][x + 1]) %= mod;
            (ans += dp[step % 2][x - 1][x]) %= mod;
            (ans += dp[step % 2][x][x]) %= mod;
        }
        printf("%d\n", ans);
        return;
    }
    for (int x1 = 1; x1 <= step; ++x1)
    {
        int y1 = step - x1 + 1;
        if (y1 < 1 || y1 > m)
            continue;
        for (int x2 = 1; x2 <= step; ++x2)
        {
            int y2 = step - x2 + 1;
            x2 = n - x2 + 1;
            y2 = m - y2 + 1;
            if (y2 < 1 || y2 > m || !((x1 == x2 && y2 == y1 + 1) || (y1 == y2 && x2 == x1 + 1)))
            {
                x2 = n + 1 - x2;
                continue;
            }
            (ans += dp[step % 2][x1][x2]) %= mod;
            x2 = n + 1 - x2;
        }
    }
    printf("%d\n", ans);
}
int main()
{
    AC();
    return 0;
}
资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在 IT 领域,文档格式转换是常见需求,尤其在处理多种文件类型时。本文将聚焦于利用 Java 技术栈,尤其是 Apache POI 和 iTextPDF 库,实现 doc、xls(涵盖 Excel 2003 及 Excel 2007+)以及 txt、图片等格式文件向 PDF 的转换,并实现在线浏览功能。 先从 Apache POI 说起,它是一个强大的 Java 库,专注于处理 Microsoft Office 格式文件,比如 doc 和 xls。Apache POI 提供了 HSSF 和 XSSF 两个 API,其中 HSSF 用于读写老版本的 BIFF8 格式(Excel 97-2003),XSSF 则针对新的 XML 格式(Excel 2007+)。这两个 API 均具备读取和写入工作表、单元格、公式、样式等功能。读取 Excel 文件时,可通过创建 HSSFWorkbook 或 XSSFWorkbook 对象来打开相应格式的文件,进而遍历工作簿中的每个 Sheet,获取行和列数据。写入 Excel 文件时,创建新的 Workbook 对象,添加 Sheet、Row 和 Cell,即可构建新 Excel 文件。 再看 iTextPDF,它是一个用于生成和修改 PDF 文档的 Java 库,拥有丰富的 API。创建 PDF 文档时,借助 Document 对象,可定义页面尺寸、边距等属性来定制 PDF 外观。添加内容方面,可使用 Paragraph、List、Table 等元素将文本、列表和表格加入 PDF,图片可通过 Image 类加载插入。iTextPDF 支持多种字体和样式,可设置文本颜色、大小、样式等。此外,iTextPDF 的 TextRenderer 类能将 HTML、
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值