hdu 4558 动态规划

本文介绍了一种算法,用于计算在一个n×m的矩阵中,从任意起点到终点的所有路径数量,路径上人和剑的能量值需保持一致,且只能向右或向下移动。采用动态规划方法,通过枚举能量差值进行状态转移。

题意: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;
}

 

转载于:https://www.cnblogs.com/ts65213/archive/2013/05/26/3099978.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值