码迷,mamicode.com
首页 > 其他好文 > 详细

UVa 10564 - Paths through the Hourglass(DP)

时间:2015-05-08 09:42:26      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:dp   uva   

Description

Problem F
Paths through the Hourglass
Input:
Standard Input

Output: Standard Output

Time Limit: 2 Seconds

 In the hourglass to the right a path is marked. A path always starts at the first row and ends at the last row. Each cell in the path (except the first) should be directly below to the left or right of the cell in the path in the previous row. The value of a path is the sum of the values in each cell in the path.

A path is described with an integer representing the starting point in the first row (the leftmost cell being 0) followed by a direction string containing the letters L and R, telling whether to go to the left or right. For instance, the path to the right is described as 2 RRRLLRRRLR.

Given the values of each cell in an hourglass as well as an integer S, calculate the number of distinct paths with value S. If at least one path exist, you should also print the path with the lowest starting point. If several such paths exist, select the one which has the lexicographically smallest direction string.

Input

The input contains several cases. Each case starts with a line containing two integers N and S (2≤N≤20, 0≤S<500), the number of cells in the first row of the hourglass and the desired sum. Next follows 2N-1 lines describing each row in the hourglass. Each line contains a space separated list of integers between 0 and 9 inclusive. The first of these lines will contain N integers, then N-1, ..., 2, 1, 2, ..., N-1, N.

The input will terminate with N=S=0. This case should not be processed. There will be less than 30 cases in the input.

 

 

Output

For each case, first output the number of distinct paths. If at least one path exist, output on the next line the description of the path mentioned above. If no path exist, output a blank line instead.

题意:有一个沙漏,如下图所示。你可以从第一行的任意一格开始往下走,向左下方或者右下方走,但不能走出沙漏。你的目标是让沿途所有经过的整数之和恰好为一个整数 s ,求出符合上述条件的路径总数,以及打印一条路径。如果有多条路径,选择起点编号最小的,每一行的格子编号从 0 开始。如果仍然有多个解,移动序列(L代表左移,R代表右移)的字典序应最小。如果不存在可行的路径,输出 0,并且在 0 的下面输出一行空行。

思路:看了一下别人的做法,坐标构造方面可谓大神自由妙计啊。把纵坐标构造成以下形式,用 str 数组保存

      K 

K        K+1

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

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

从下向上遍历。dp 数组记得定义为 long long。

最后用 dfs 打印字典序最小的路径。

技术分享

<span style="font-size:18px;">
str[1][1]=6  str[1][2]=7  str[1][3]=2  str[1][4]=3   str[1][5]=6   str[1][6]=8 
str[2][2]=1  str[2][3]=8  str[2][4]=0  str[2][5]=7   str[2][6]=1 
str[3][3]=2  str[3][4]=6  str[3][5]=5  str[3][6]=7 
str[4][4]=3  str[4][5]=1  str[4][6]=0 
str[5][5]=7  str[5][6]=6 
str[6][6]=8 
str[7][6]=8  str[7][7]=8 
str[8][6]=6  str[8][7]=5  str[8][8]=3 
str[9][6]=9  str[9][7]=5  str[9][8]=9  str[9][9]=5 
str[10][6]=6 str[10][7]=4 str[10][8]=4 str[10][9]=1  str[10][10]=3 
str[11][6]=2 str[11][7]=6 str[11][8]=9 str[11][9]=4  str[11][10]=3 str[11][11]=8

</span>
技术分享


#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;

#define ll long long
const double PI = acos(-1.0);
const double e = 2.718281828459;
const double eps = 1e-8;
const int MAXN = 55;
int str[MAXN][MAXN];
ll dp[MAXN][MAXN][550];
int n;

void dfs(int x, int y, int s)
{
    if(x == 2*n-1)
        return ;
    int v = str[x][y];
    if(dp[x+1][y][s-v])
    {
        printf("L");
        dfs(x+1, y, s-v);
    }
    else
    {
        printf("R");
        dfs(x+1, y+1, s-v);
    }
}

int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int s;
    while(cin>>n>>s)
    {
        if(!n && !s)
            break;
        memset(str, 0, sizeof(str));
        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]);
            }
        }
        int t;
        memset(dp, 0, sizeof(dp));
        for(int i = n; i <= 2*n-1; i++)
        {
            t = str[2*n-1][i];
            dp[2*n-1][i][t] = 1;
        }
        for(int i = 2*n-2; i >= n; i--)
        {
            for(int j = n; j <= i; j++)
            {
                int v = str[i][j];
                for(int k = v; 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++)
            {
                int v = str[i][j];
                for(int k = v; k <= s; k++)
                {
                    dp[i][j][k] = dp[i+1][j][k-v]+dp[i+1][j+1][k-v];
                }
            }
        }
        ll ans = 0;
        for(int i = 1; i <= n; i++)
        {
            ans += dp[1][i][s];
        }
        cout<<ans<<endl;
        for(int i = 1; i <= n; i++)
        {
            if(dp[1][i][s])
            {
                printf("%d ", i-1);
                dfs(1, i, s);
                break;
            }
        }
        printf("\n");
    }
    return 0;
}





UVa 10564 - Paths through the Hourglass(DP)

标签:dp   uva   

原文地址:http://blog.csdn.net/u014028317/article/details/45566321

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!