CF 316div2 E.Pig and Palindromes
E. Pig and Palindromes
Peppa the Pig was walking and walked into the forest. What a strange coincidence! The forest has the shape of a rectangle, consisting of n rows and m columns. We enumerate the rows of the rectangle from top to bottom with numbers from 1 to n, and the columns — from left to right with numbers from 1 to m. Let’s denote the cell at the intersection of the r-th row and the c-th column as (r, c).
Initially the pig stands in cell (1, 1), and in the end she wants to be in cell (n, m). Since the pig is in a hurry to get home, she can go from cell (r, c), only to either cell (r + 1, c) or (r, c + 1). She cannot leave the forest.
The forest, where the pig is, is very unusual. Some cells of the forest similar to each other, and some look very different. Peppa enjoys taking pictures and at every step she takes a picture of the cell where she is now. The path through the forest is considered to be beautiful if photographs taken on her way, can be viewed in both forward and in reverse order, showing the same sequence of photos. More formally, the line formed by the cells in order of visiting should be a palindrome (you can read a formal definition of a palindrome in the previous problem).
Count the number of beautiful paths from cell (1, 1) to cell (n, m). Since this number can be very large, determine the remainder after dividing it by 109 + 7.
Input 
The first line contains two integers n, m (1 ≤ n, m ≤ 500) — the height and width of the field.
Each of the following n lines contains m lowercase English letters identifying the types of cells of the forest. Identical cells are represented by identical letters, different cells are represented by different letters.
Output 
Print a single integer — the number of beautiful paths modulo 109 + 7.
Sample test(s)
input 
3 4 
aaab 
baaa 
abba 
output 
3
题意概述:在一个n*m的矩阵中,每个格子都有一个字母。你从(1,1)出发前往(n,m),每次仅仅能向下或向右。当到达终点时,把你经过的字母写下来。产生一个字符串。求有多少种走成回文的方案。
每一次仅仅能向下或向右。所以考虑能够用dp做。考虑曼哈顿距离 
按距离原点和终点的曼哈顿距离同样的两个点做状态转移 
想象有两个点分别从起点和终点同一时候向中间走 
用f[p1][p2] 表示 第一个点在p1位置第二个点在p2位置时的从起点终点同一时候走过的同样字母路径的合法状态数
f[p1][p2]=f[p1_f1][p2_f1]+f[p1_f1][p2_f2]+f[p1_f2][p2_f1]+f[p1_f2][p2_f2]
p1_f1,p1_f2,p2_f1,p2_f2分别表示p1和p2的前驱点
因为坐标非常大,须要用滚动数组优化。斜着循环每个点也须要一些小技巧详细看代码~
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int MAX=505;
const int MOD=1e9+7;
char s[MAX][MAX];
int f[MAX][MAX]={0};
int f_[MAX][MAX];
int i,j,m,n,k,dis;
struct point{
    int x,y;
};
point next_1(point a)
{
    if (a.y==1&&a.x<n)
        a.x++;
    else
        a.y++;
    return a;
}
point next_2(point a)
{
    if (a.x==n&&a.y>1)
        a.y--;
    else
        a.x--;
    return a;
}
point nex(point a)
{
    a.x--;
    a.y++;
    return a;
}
int main()
{
    cin>>n>>m;
    int ans=0;
    getchar();
    for (i=1;i<=n;i++)
    {
        for (j=1;j<=m;j++)
            scanf("%c",&s[i][j]);
        getchar();
    }
    point a,b,p1,p2;
    a.x=a.y=1;
    b.x=n;b.y=m;
    int max_=(m+n)/2;
    if (s[1][1]==s[n][m])
        f[1][n]=1;
    else
        f[1][n]=0;
    if (m+n<=3)
    {
        cout<<f[1][n]<<endl;
        return 0;
    }
    for (dis=2;dis<=max_;dis++)
    {
        a=next_1(a);
        b=next_2(b);
        for (i=1;i<=500;i++)
            for (j=1;j<=500;j++)
            {
                f_[i][j]=f[i][j];
                f[i][j]=0;
            }
        for (p1=a;p1.y<=m&&p1.x>=1;p1=nex(p1))
            for (p2=b;p2.y<=m&&p2.x>=1;p2=nex(p2))
                if (s[p1.x][p1.y]==s[p2.x][p2.y])
                {
                    f[p1.x][p2.x]=((f_[p1.x-1][p2.x]+f_[p1.x-1][p2.x+1])%MOD+(f_[p1.x][p2.x]+f_[p1.x][p2.x+1])%MOD)%MOD;
                    if (((p1.x==p2.x)&&(abs(p1.y-p2.y)<=1))||((p1.y==p2.y)&&(abs(p1.x-p2.x)<=1)))
                        ans=(ans+f[p1.x][p2.x])%MOD;
                }
    }
    cout<<ans<<endl;
    return 0;
}
贴一个cf上看到的位运算的程序,相当简短
#include <bits/stdc++.h>
using namespace std;
#define f(i,n) for(int i=0;i<(n);i++)
#define fr(i,n) for(int i=n;i--;)
char x[500][501];
int d[2][501][501],n,m;
main(){
    cin>>n>>m;
    f(i,n) cin>>x[i];
    f(ei,n) fr(si,n) fr(sj,m){
        auto& c=d[ei&1][si][sj]=0,ej=n+m-2-si-sj-ei;
        if(si<=ei&&sj<=ej&&x[si][sj]==x[ei][ej]&&!(c=abs(si-ei)+abs(sj-ej)<=1))
            f(i,2) f(j,2) c=(c+d[ei-!j&1][si+!i][sj+!!i])%((int)1e9+7);
    }
    cout<<d[~n&1][0][0]<<'\n';
}
CF 316div2 E.Pig and Palindromes的更多相关文章
- codeforces  570 E. Pig and Palindromes (DP)
		
题目链接: 570 E. Pig and Palindromes 题目描述: 有一个n*m的矩阵,每个小格子里面都有一个字母.Peppa the Pig想要从(1,1)到(n, m).因为Peppa ...
 - Codeforces Round #316 (Div. 2)E. Pig and Palindromes DP
		
E. Pig and Palindromes Peppa the Pig was walking and walked into the forest. What a strange coinci ...
 - 【25.64%】【codeforces 570E】Pig and Palindromes
		
time limit per test4 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
 - Codeforces 570E - Pig and Palindromes - [滚动优化DP]
		
题目链接:https://codeforces.com/problemset/problem/570/E 题意: 给出 $n \times m$ 的网格,每一格上有一个小写字母,现在从 $(1,1)$ ...
 - D Tree Requests dfs+二分 D Pig and Palindromes -dp
		
D time limit per test 2 seconds memory limit per test 256 megabytes input standard input output stan ...
 - CF570E Pig and Palindromes
		
完全不会这种类型的$dp$啊…… 考虑回文串一定是可以拆分成(偶数个字母 + 偶数个字母)或者(偶数个字母 + 一个字母 +偶数个字母),两边的偶数个字母其实是完全对称的.因为这道题回文串的长度是给定 ...
 - CodeForces 570E DP Pig and Palindromes
		
题意:给出一个n行m列的字符矩阵,从左上角走到右下角,每次只能往右或者往下走,求一共有多少种走法能得到回文串. 分析: 可以从两头开始考虑,每次只走一样字符的格子,这样得到的两个字符串拼起来之后就是一 ...
 - Codeforces 570 - A/B/C/D/E - (Done)
		
链接:https://codeforces.com/contest/570 A - Elections - [水] AC代码: #include<bits/stdc++.h> using ...
 - CF 568A(Primes or Palindromes?-暴力推断)
		
A. Primes or Palindromes? time limit per test 3 seconds memory limit per test 256 megabytes input st ...
 
随机推荐
- HDU 2504 又见GCD(数论,最大公约数)
			
又见GCD Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
 - MySQL逻辑架构简介
			
1.Connectors指的是不同语言中与SQL的交互2 Management Serveices & Utilities: 系统管理和控制工具3 Connection Pool: 连接池管理 ...
 - USACO1.3.2修理牛棚
			
在学习一段时间贪心并写了一些贪心题之后,又一次看到了农夫和牛幸福美满的生活故事(雾).嘛,闲话少说,上题目 在一个暴风雨的夜晚,农民约翰的牛棚的屋顶.门被吹飞了. 好在许多牛正在度假,所以牛棚没有住满 ...
 - 树状数组【CF703D】Mishka and Interesting sum
			
Description 给你n( 1<=n<=1000000)个数,以及m(1<=m<=1000000)个询问,每个询问包括l和r,问你在这n个数中,区间l~r,出现偶数个数的 ...
 - POJ1386Play on Words(欧拉回路)
			
Play on Words Time Limit: 1000MS Memory L ...
 - JAVA net 笔记
			
1.InetAddress 获取主机ip等 2.URL 3.URLConnection (url.openConnection() 创建对象) 4.BufferedReader 5.InputStre ...
 - 【线段树】bzoj3922 Karin的弹幕
			
设置一个值K. d<=K:建立多组线段树:d>K:暴力. 最优时间复杂度的伪计算: O(n*K*logn(建树)+m*logn(询问类型1)+m*n/K(询问类型2)+m*K*logn(修 ...
 - 【树链剖分】【分块】【最近公共祖先】【块状树】bzoj1984 月下“毛景树”
			
裸题,但是因为权在边上,所以要先把边权放到这条边的子节点上,然后进行链更新/查询的时候不能更新/查询其lca. #include<cstdio> #include<cmath> ...
 - 【最大流】【费用流】bzoj1834 [ZJOI2010]network 网络扩容
			
引用题解: 最大流+费用流. 第一问最大流即可. 第二问为“最小费用最大流”. 由题意,这一问的可转化为在上一问的“残量网络”上,扩大一些边的容量,使能从新的图中的最大流为k. 那么易得:对于还有剩余 ...
 - python3 开发面试题(生成列表)6.1
			
话不多说直接上题: 生成如下列表: [[0, 0, 0, 0, 0], [0, 1, 2, 3, 4], [0, 2, 4, 6, 8], [0, 3, 6, 9, 12]] # 方式一 list1 ...