51nod-1503猪和回文

题目来源:  CodeForces
基准时间限制:2 秒 空间限制:131072 KB 分值: 40  难度:4级算法题
 收藏
 关注

一只猪走进了一个森林。很凑巧的是,这个森林的形状是长方形的,有n行,m列组成。我们把这个长方形的行从上到下标记为1到n,列从左到右标记为1到m。处于第r行第c列的格子用(r,c)表示。

刚开始的时候猪站在(1,1),他的目标是走到(n,m)。由于猪回家心切,他在(r,c)的时候,只会往(r+1,c)或(r,c+1)走。他不能走出这个森林。

这只猪所在的森林是一个非同寻常的森林。有一些格子看起来非常相似,而有一些相差非常巨大。猪在行走的过程中喜欢拍下他经过的每一个格子的照片。一条路径被认为是漂亮的当且仅当拍下来的照片序列顺着看和反着看是一样的。也就是说,猪经过的路径要构成一个回文。

数一数从(1,1)到(n,m)有多少条漂亮路径。答案可能非常巨大,请输出对 109+7 取余后的结果。

样例解释:有三种可能

  


Input
单组测试数据。
第一行有两个整数 n,m (1≤n,m≤500),表示森林的长和宽。
接下来有n行,每行有m个小写字母,表示每一个格子的类型。同一种类型用同一个字母表示,不同的类型用不同的字母表示。
Output
输出答案占一行。
Input示例
3 4
aaab
baaa
abba
Output示例
3

题解:额,一开始我是真不知道咋搞。。万恶的回文。。

看了大佬的博客再次对自己蒟蒻的现状深深无奈~

从左上角和右下角同时走,一共有四种状态,左上往右+右下往上,左上往右+右下往左,左上往下+右下往上,左上往下+右下往左。说到这,很明显发现我们可以用dp[i][j][x][y]来处理,跟一般的dp没什么区别。但如此操作会超内存。我们发现,x + y + i + j = n + m + 2;故我们只需要三维即可。三维仍然超。我们继续发现,每次其实只需要用到第一维的两个状态,故使用滚动数组。

最终dp[2][][]来处理即可

AC代码

#include <stdio.h>
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cmath>
 
using namespace std;

const int maxn = 505, mod = 1e9 + 7;
int dp[2][maxn][maxn];

char map1[maxn][maxn];

bool can(int i, int j, int x, int y){
	if(i == x && j == y)
		return true;
	if(i + 1 == x && j == y)
		return true;
	if(i == x && j + 1 == y)
		return true;
	return false;
}

int main(){
	int n, m, ans;
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i++)
		scanf("%s", map1[i] + 1);
	memset(dp, 0, sizeof(dp));
	if(map1[1][1] == map1[n][m])
		dp[1][1][n] = 1;
	ans = 0;
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= m; j++){
			for(int x = n; x >= 1; x--){
				int y = n + m - x - i - j + 2;
				if(y <= 0 || y > m)
					continue;
				if(2 * i + 2 * j - 2 > n + m)
					continue;
				if(map1[i][j] != map1[x][y])
					continue;
				dp[i & 1][j][x] = (dp[i & 1][j][x] + dp[i & 1][j - 1][x]) % mod;
				dp[i & 1][j][x] = (dp[i & 1][j][x] + dp[i & 1][j - 1][x + 1]) % mod;
				dp[i & 1][j][x] = (dp[i & 1][j][x] + dp[(i + 1) & 1][j][x]) % mod;
				dp[i & 1][j][x] = (dp[i & 1][j][x] + dp[(i + 1) & 1][j][x + 1]) % mod;
				if(can(i, j, x, y))
					ans = (ans + dp[i & 1][j][x]) % mod;
			}
		}
		for(int j = 1; j <= m; j++)
			for(int x = 1; x <= n; x++)
				dp[(i + 1) & 1][j][x] = 0;
	} 
	printf("%d\n", ans);	
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_37064135/article/details/80412004
今日推荐