uva10564 - Paths through the Hourglass(巧妙动归)

此题的巧妙之处在于读入数据的坐标安排,

为了固定的形成

      K

K          K+1 的状态。。。

在str[i][j]的 j 坐标构造方面可谓大神自由妙计呀,http://hi.baidu.com/arosliu/item/e500c8e5b7a5a0c3bbf37d8e

状态:dp[i][j][k]从(i,j)出发路径上的和为k的路径数目。

状态转移:dp[i][j][k] = dp[i+1][j][k-v]+dp[i+1][j+1][k-v];

代码如下:

#include <cstdio>
#include <cstring>
#define N 50
#define S 505
long long dp[N][N][S];
int n, s, str[N][N];
int abs(int x){ return x<0?-x:x; }
void printf_ans(int x, int y, int v)
{
    if(x==2*n-1) return ;
    int ss = str[x][y];
    if(dp[x+1][y][v-ss]) { printf("L"); printf_ans(x+1,y,v-ss); }
    else { printf("R"); printf_ans(x+1,y+1,v-ss); }
}
int main ()
{
    while(scanf("%d %d",&n, &s), s+n)
    {
        for(int i = 1; i <= n; i++)
        {
            for(int j = i; j <= n; j++)
                scanf("%d",&str[i][j]);
        }
        for(int i = n+1; i <= 2*n-1; i++)
        {
            for(int j = n; j <= i; j++)
                scanf("%d",&str[i][j]);
        }
        memset(dp,0,sizeof(dp));
        for(int i = n; i <= 2*n-1; i++)
        {
            int tt = str[2*n-1][i];
            dp[2*n-1][i][tt] = 1;
        }
        for(int i = 2*n-2; i >= n; i--)
        {
            for(int j = n; j <= i; j++)
                for(int v = str[i][j], k = str[i][j]; k <= s; k++)
                    dp[i][j][k] = dp[i+1][j][k-v]+dp[i+1][j+1][k-v];
        }
        for(int i = n-1; i >= 1; i--)
        {
            for(int j = i; j <= n; j++)
                for(int v = str[i][j], k = str[i][j]; k <= s; k++)
                    dp[i][j][k] = dp[i+1][j][k-v]+dp[i+1][j+1][k-v];
        }
        long long ans = 0;
        for(int i = 1; i <= n; i++) ans+=dp[1][i][s];
        printf("%lld\n", ans);
        for(int i = 1; i <= n; i++) if(dp[1][i][s])
        {
            printf("%d ",i-1);
            printf_ans(1,i,s);
            break;
        }
        printf("\n");
    }
    return 0;
}


 

你可能感兴趣的:(uva10564 - Paths through the Hourglass(巧妙动归))