题意:
如图
走这个沙漏,给沙漏的大小和一个数字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]);
}
}
}
}