uva 10564 沙漏

题意:

如图

走这个沙漏,给沙漏的大小和一个数字s,问最后有多少条路可以到达底部使得沙漏路径和为s。

若有多条路径,打印起点最低的,that means ,打印第一行最靠左边的路。


解析:

自己一直TLE,看了一个大牛的代码。

他是这样处理的:因为上下沙漏走左右是不同的,上沙漏往下走的时候,向左是( i + 1, j - 1 )向右是( i + 1, j );

而当走到下沙漏时,向下走,向左是( i + 1, j ),向右是( i + 1, j + 1 );

因此直接开一个R[i][j]和L[i][j]的数组,表示当前i,j点向左走,右走的横坐标。

然后怎么判断走出边界呢,是直接开始赋值的时候就把边界外的值全部设为-1,因为题目里面说

’Each line contains a space separated list of integers between 0 and 9 inclusive‘

果然每一个条件都是精心设计好的,若走到值为-1的地方就是走出边界了。

然后枚举起点,为了打印的是最low的起点,从右往左扫,累计和就可以了。

打印路径时,还是一步一步深搜下去就ok啦。


代码:

///ac 0.038s
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>

#define LL long long

using namespace std;
const int maxn = 20 * 2 + 10;
const int maxd = 500 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);

int L[maxn][maxn], R[maxn][maxn];//nb...
int num[maxn][maxn];
LL dp[maxn][maxn][maxd];
bool vis[maxn][maxn][maxd];
int n, s;
//
LL dfs(int i, int j, int sum)
{
    LL& res = dp[i][j][sum];
    if (vis[i][j][sum])
        return res;
    vis[i][j][sum] = true;
    if (num[i][j] == -1 || sum < 0)
        return res = 0;
    if (2 * n - 1 == i)
    {
        if (sum == num[i][j])
        {
            return res = 1;
        }
        else
        {
            return res = 0;
        }
    }
    else
    {
        res = dfs(i + 1, L[i][j], sum - num[i][j]) + dfs(i + 1, R[i][j], sum - num[i][j]);
    }
    return res;
}
//
void print_path(int i, int j, int sum)
{
    if (i == 2 * n - 1)
    {
        printf("\n");
        return;
    }
//    if (dfs(i + 1, L[i][j], sum - num[i][j]) > 0)//have path
    if (dp[i + 1][L[i][j]][sum - num[i][j]] > 0)
    {
        printf("L");
        print_path(i + 1, L[i][j], sum - num[i][j]);
    }
    else
    {
        printf("R");
        print_path(i + 1, R[i][j], sum - num[i][j]);
    }
}

///TLE...
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>

#define LL long long

using namespace std;
const int maxn = 20 * 2 + 10;
const int maxd = 500;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);

int num[maxn][maxn];
int dp[maxn][maxn][maxd];// + num[i][j] = k  's numbers;
int n, s;
int pos;
char ans[maxn], tmp[maxn];

void find_pos(int i, int j, int sum)
{
    if (n <= i)
    {
        if (sum - num[i][j] >= 0 && dp[i - 1][j][sum - num[i][j]])
        {
            tmp[i - 1] = 'L';
            find_pos(i - 1, j, sum - num[i][j]);
        }
        if (sum - num[i][j] >= 0 && j - 1 >= 0 && dp[i - 1][j - 1][sum - num[i][j]])
        {
            tmp[i - 1] = 'R';
            find_pos(i - 1, j - 1, sum - num[i][j]);
        }
    }
    else
    {
        if (i == 1)
        {
            if (sum - num[i][j] >= 0 && dp[i - 1][j + 1][sum - num[i][j]])
            {
                tmp[i - 1] = 'L';
                int t = j + 1;
                if (pos > t)
                {
                    pos = t;
                    strcpy(ans, tmp);
                }
                else if (pos == t)
                {
                    if (strcmp(ans, tmp) > 0)
                        strcpy(ans, tmp);
                }
            }
            if (sum - num[i][j] >= 0 && dp[i - 1][j][sum - num[i][j]])
            {
                tmp[i - 1] = 'R';
                int t = j;
                if (pos > t)
                {
                    pos = t;
                    strcpy(ans, tmp);
                }
                else if (pos == t)
                {
                    if (strcmp(ans, tmp) > 0)
                        strcpy(ans, tmp);
                }
            }
        }
        else
        {
            if (sum - num[i][j] >= 0 && dp[i - 1][j + 1][sum - num[i][j]])
            {
                tmp[i - 1] = 'L';
                find_pos(i - 1, j + 1, sum - num[i][j]);
            }
            if (sum - num[i][j] >= 0 && dp[i - 1][j][sum - num[i][j]])
            {
                tmp[i - 1] = 'R';
                find_pos(i - 1, j, sum - num[i][j]);
            }
        }
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值