【LOJ】#2178. 「BJOI2017」机动训练

题解

遇见平方和就转有序对呗

dp类似从很多点出发每次走一步的转移方式

然后我too naive的,枚举路径长度来决定更新次数,愉快TLE

改成记搜就过了

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define MAXN 100005
#define mo 994711
//#define ivorysi
using namespace std;
typedef long long int64;
typedef long double db;
typedef unsigned int u32;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 + c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {putchar('-');x = -x;}
    if(x >= 10) out(x / 10);
    putchar('0' + x % 10);
}
const int MOD = 1000000009;
int N,M,dp[35][35][35][35],cur,cnt;
char s[35][35];
int dx[2][5],dy[2][5];
int X[3] = {0,1,1};
int Y[3] = {1,0,1};
int inc(int a,int b) {
    return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
    return 1LL * a * b % MOD;
}
void update(int &x,int y) {
    x = inc(x,y);
}
inline bool check(int on,int x,int y,int d,int c) {
    if(X[c] && (!dx[on][d])) return false;
    if(Y[c] && (!dy[on][d])) return false;
    int tx = x + X[c] * dx[on][d];
    int ty = y + Y[c] * dy[on][d];
    if(tx < 1 || tx > N) return false;
    if(ty < 1 || ty > M) return false;
    return true;
}
int DP(int x1,int y1,int x2,int y2,int l,int v) {
    if(dp[x1][y1][x2][y2] != -1) return dp[x1][y1][x2][y2];
    if(s[x1][y1] != s[x2][y2]) return 0;
    dp[x1][y1][x2][y2] = 1;
    for(int a = 0 ; a <= 2 ; ++a) {
	for(int b = 0 ; b <= 2 ; ++b) {
	    if(check(0,x1,y1,l,a) && check(1,x2,y2,v,b)) {
		int tx1 = x1 + X[a] * dx[0][l];
		int ty1 = y1 + Y[a] * dy[0][l];
		int tx2 = x2 + X[b] * dx[1][v];
		int ty2 = y2 + Y[b] * dy[1][v];
		update(dp[x1][y1][x2][y2],DP(tx1,ty1,tx2,ty2,l,v));
	    }
	}
    }
    return dp[x1][y1][x2][y2];
}
int Calc(int Len) {
    cur = 0;
    int res = 0;
    
    for(int l = 0 ; l <= 3 ; ++l) {
	for(int v = 0 ; v <= 3 ; ++v) {
	    memset(dp,-1,sizeof(dp));
	    for(int i = 1 ; i <= N ; ++i) {
		for(int j = 1 ; j <= M ; ++j) {
		    for(int k = 1 ; k <= N ; ++k) {
			for(int h = 1 ; h <= M ; ++h) {
			    if(s[i][j] != s[k][h]) continue;
			    update(res,inc(DP(i,j,k,h,l,v),MOD - 1));
	       
			}
		    }
		}
	    }
	}
    }
    return res;
}
void Solve() {
    read(N);read(M);
    int ans = 0;
    for(int i = 1 ; i <= N ; ++i) scanf("%s",s[i] + 1);
    dx[0][0] = dx[1][0] = 1;dx[0][1] = dx[1][1] = 1;dx[0][2] = dx[1][2] = -1;dx[0][3] = dx[1][3] = -1;
    dy[0][0] = dy[1][0] = 1;dy[0][1] = dy[1][1] = -1;dy[0][2] = dy[1][2] = 1;dy[0][3] = dy[1][3] = -1;
    update(ans,Calc(N + M));
    dx[0][0] = 1;dx[0][1] = -1;dx[0][2] = 0;dx[0][3] = 0;
    dy[0][0] = 0;dy[0][1] = 0;dy[0][2] = 1;dy[0][3] = -1;
    update(ans,MOD - Calc(max(N,M)));
    for(int i = 0 ; i <= 3 ; ++i) {
	swap(dx[0][i],dx[1][i]);
	swap(dy[0][i],dy[1][i]);
    }
    update(ans,MOD - Calc(max(N,M)));
    memcpy(dx[0],dx[1],sizeof(dx[1]));
    memcpy(dy[0],dy[1],sizeof(dy[1]));
    update(ans,Calc(max(N,M)));
    out(ans);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}
posted @ 2018-09-19 15:18  sigongzi  阅读(341)  评论(0编辑  收藏  举报