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;
}

 

posted @ 2013-05-26 14:12  心向往之  阅读(167)  评论(4编辑  收藏  举报