51nod 1503 猪和回文(dp滚存)
大意:在一个n*m的矩形中从(1,1)走到(n,m)而且走过的路径是一条回文串,统计方案数
sol:我们考虑从(1,1)和(n,m)两端开始算,这样就只要保证每次经过的字符一样就可以满足回文了,因为一定有一个循环需要枚举步数,知道了步数自然只要知道了x坐标就可以算出y坐标了,于是只要枚举x1和x2了,因为当前这步一定是从上一步转移过来的,就可以滚存了
#include<bits/stdc++.h> using namespace std; #define Mod 1000000007 long long n, m, f[2][505][505], ans = 0; char Map[505][505]; inline void Add(long long &x, long long y){x = (x + y) % Mod;} int main() { freopen("51nod1503.in","r",stdin); while(~scanf("%lld%lld", &n, &m)) { ans = 0; for(long long i = 1; i <= n; i++) scanf("%s", Map[i] + 1); if(Map[1][1] != Map[n][m]) { printf("0\n"); continue; } long long cur = 0; f[cur][1][n] = 1; for(long long step = 1; step <= (n + m - 2) / 2; step++) { cur ^= 1; for(long long i = 1; i <= n; i++) for(long long j = 1; j <= n; j++) f[cur][i][j] = 0; for(long long x1 = 1; x1 <= n && x1 - 1 <= step; x1++) for(long long x2 = n; x2 >= 1 && n - x2 <= step; x2--) { long long y1 = 1 + (step - (x1 - 1)); long long y2 = m - (step - (n - x2)); if (Map[x1][y1] != Map[x2][y2]) continue; Add(f[cur][x1][x2], f[cur ^ 1][x1 - 1][x2 + 1]); Add(f[cur][x1][x2], f[cur ^ 1][x1 - 1][x2]); Add(f[cur][x1][x2], f[cur ^ 1][x1][x2 + 1]); Add(f[cur][x1][x2], f[cur ^ 1][x1][x2]); } } for(long long i = 1; i <= n; i++) Add(ans, f[cur][i][i]); if((n + m) & 1) for(long long i = 1; i < n; i++) Add(ans, f[cur][i][i + 1]); printf("%lld\n", ans); } }
河田は河田、赤木は赤木……。
私は誰ですか。教えてください、私は誰ですか。
そうだ、俺はあきらめない男、三井寿だ!