hdu 4558 动态规划
题意:n×m (1<= N, M <=477) 的矩阵,a[i][j]表示第i行第j列的能量值,可以从任意点出发,任意点停止,但只能往右或往下走。
第一步给自己补充能量,第二步给剑补充能量,依次循环补充。能量值0~10,若当前为10,又补充了1的能量,则能量变成0。
要求离开的时候,人和剑的能量值相同,问有多少种不同的走法?结果对1 000 000 007取余。
分析:枚举人和剑的差值,人比剑多s,相当于人比剑少11-s。。。
设dp[x][y][i]表示在(x,y)位置,差值为i的方案数,
dp[x][y][i] = ( dp[x][y][i] + dp[x+1][y][j] ) % mod;
dp[x][y][i] = ( dp[x][y][i] + dp[x][y+1][j] ) % mod;
j为相邻格子的能量值,由于人和剑交替补充,对j取反为11-j,又当前格子本身有差值a[x][y],
所以i=11-j+a[x][y], j=(11-i+a[x][y]) % 11;
int dx[] = {1,0,1,0};//up Right down Left int dy[] = {0,1,0,-1}; const int M = 480, N = 11, mod = 1000000007; char s[M]; int a[M][M], n, m, ans; int dp[M][M][N]; int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif int T; scanf("%d", &T); FOE(t, 1, T){ ans = 0; memset(dp, 0, sizeof dp); scanf("%d%d", &n, &m); FOR(x, 0, n) { scanf("%s", s); FOR(y, 0, m) a[x][y] = s[y]-'0'; } FOD(x, n-1, 0) { FOD(y, m-1, 0) { int v = a[x][y]; FOR(i, 0, N) { FOR(r, 0, 2) { int xx=x+dx[r], yy=y+dy[r]; if(xx>=n || yy>=m) continue; int temp = (11-i+v) % 11; dp[x][y][i] = (dp[x][y][i] + dp[xx][yy][temp]) % mod; } } dp[x][y][v]++; ans = ( ans + dp[x][y][0] ) % mod; } } printf("Case %d: %d\n", t, ans); } return 0; }