[Usaco2015 OPEN] Palindromic Paths

[题目链接]

https://www.lydsy.com/JudgeOnline/problem.php?id=4098

[算法]

显然 , 回文路径中第i个字母的位置(x , y)必然满足 : x + y - 1 = i

用f[i][j][k]表示现在在第i步 , 左上的横坐标为j , 右下的横坐标为k , 有多少种方案使得两边路径上的字母序列相同 , DP即可

时间复杂度 : O(N ^ 3)

滚动数组 , 将空间复杂度优化为O(N ^ 2)

[代码]

#include<bits/stdc++.h>
using namespace std;
#define MAXN 510
const int P = 1e9 + 7;

int n;
int f[2][MAXN][MAXN];
char mp[MAXN][MAXN];

inline void update(int &x , int y)
{
        x += y;
        x %= P;
}
inline bool valid(int x , int y)
{
        return x >= 1 && x <= n && y >= 1 && y <= n;
}

int main()
{

        scanf("%d",&n);
        for (int i = 1; i <= n; i++) scanf("%s",mp[i] + 1);
        if (mp[1][1] == mp[n][n])
        {
                f[1][1][n] = 1;
        } else
        {
                printf("0\n");
                return 0;
        }
        for (int i = 1; i <= n; i++)
        {
                int now = i & 1 , nxt = now ^ 1;
                memset(f[nxt] , 0 , sizeof(f[nxt]));
                for (int x = 1; x <= n; x++)
                {
                        for (int y = 1; y <= n; y++)
                        {
                                int t1 = i + 1 - x , t2 = 2 * n - y + 1 - i;
                                if (!valid(x , t1) || !valid(y , t2)) continue;
                                if (!f[now][x][y]) continue;
                                if (valid(x , t1 + 1))
                                {
                                        if (valid(y , t2 - 1) && mp[x][t1 + 1] == mp[y][t2 - 1])
                                                update(f[nxt][x][y] , f[now][x][y]);
                                        if (valid(y - 1 , t2) && mp[x][t1 + 1] == mp[y - 1][t2])
                                                update(f[nxt][x][y - 1] , f[now][x][y]);
                                }
                                if (valid(x + 1 , t1))
                                {
                                        if (valid(y , t2 - 1) && mp[x + 1][t1] == mp[y][t2 - 1])
                                                update(f[nxt][x + 1][y] , f[now][x][y]);
                                        if (valid(y - 1 , t2) && mp[x + 1][t1] == mp[y - 1][t2])
                                                update(f[nxt][x + 1][y - 1] , f[now][x][y]);
                                }
                        }
                }
        }
        int ans = 0;
        for (int i = 1; i <= n; i++) update(ans , f[n & 1][i][i]);
        printf("%d\n" , ans);

        return 0;

}

原文地址:https://www.cnblogs.com/evenbao/p/9846518.html

时间: 2024-08-28 13:52:04

[Usaco2015 OPEN] Palindromic Paths的相关文章

[bzoj4098] [Usaco2015 Open]Palindromic Paths

DP.. f[i][j][k]表示左上结束节点是第i条副对角线上的第j个点,右下结束节点是第n*2-i条副对角线上的第k个点,构成回文的方案数. i那维滚动一下.时间复杂度O(n^3)空间复杂度O(n^2) 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define ui unsigned

TOJ 5020: Palindromic Paths

5020: Palindromic Paths  Time Limit(Common/Java):10000MS/30000MS     Memory Limit:65536KByteTotal Submit: 8            Accepted:4 Description Given an N×N grid of fields (1≤N≤500), each labeled with a letter in the alphabet. For example: ABCD BXZXCDX

[USACO15OPEN]回文的路径Palindromic Paths

题目描述 农夫FJ的农场是一个N*N的正方形矩阵(2\le N\le 5002≤N≤500),每一块用一个字母作标记.比如说: ABCD BXZX CDXB WCBA 某一天,FJ从农场的左上角走到右下角,当然啦,每次他只能往右或者往下走一格.FJ把他走过的路径记录下来.现在,请你把他统计一下,所有路径中,回文串的数量(从前往后读和从后往前读一模一样的字符串称为回文串). 输入输出格式 输入格式: 第一行包括一个整数N,表示农场的大小,接下来输入一个N*N的字母矩阵. 输出格式: Please

【USACO 2015 Open Gold】Palindromic Paths 动态规划

链接: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/45222487"); } 题意: 从 n×n 的矩阵 左上角走到右下角会有一个长度 n+n+1 的字符串,问有多少种走法使得路径字符串为回文? 题解: f(i,j,k,l) 表示起点横着走 i 步,竖着走 j 步,终点竖着走 k 步,

USACO15OPEN Palindromic Paths

Luogu 回文串是什么?就是正着倒着读一样的字符串.既然要求回文串路线总数,不妨看成从左上角和右下角出发,每次都走一样的路线.设 \(dp[t,i,j]\) 为现在两边都走了 \(t\) 个相同的字母,左边到了第 \(i\) 行,右边到了第 \(j\) 行的方案总数.然后暴力转移,最后统计下答案就行了. 需要使用滚动数组. #include <iostream> #include <cstdio> const int MaxN = 500 + 5; const int Mod =

Codeforces Round #580 (Div. 1)

Codeforces Round #580 (Div. 1) https://codeforces.com/contest/1205 A. Almost Equal 随便构造一下吧...太水了不说了,放个代码吧. #include<bits/stdc++.h> using namespace std; void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-'

BZOJ 3887[Usaco2015 Jan]Grass Cownoisseur

题面: 3887: [Usaco2015 Jan]Grass Cownoisseur Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 237  Solved: 130[Submit][Status][Discuss] Description In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-way cow pat

bzoj4390: [Usaco2015 dec]Max Flow

4390: [Usaco2015 dec]Max Flow Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 139  Solved: 85[Submit][Status][Discuss] Description Farmer John has installed a new system of N−1 pipes to transport milk between the N stalls in his barn (2≤N≤50,000), co

bzoj3887: [Usaco2015 Jan]Grass Cownoisseur

题意: 给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1) =>有向图我们先考虑缩点.然后观察缩点后的图可以发现新的路径中必定只有一条边是反向的才符合条件.那么我们可以联想到某道最短路的题将边反向存一遍后分别从s和t跑一跑.那么这里bfs跑一跑就行了.然后有一个坑点:这种重建图的注意es和edges不然es会在中途就被修改掉了... #include<cstdio> #