这个题最初的想法是用四维数组动规 d【i】【j】【k】【w】 i j 代表 某一个位置 k 代表 到这这个 位置 的 和 w代表 从上一个格子 到这个格子的方向(1代表R 0 代表 L)
在写代码的过程中非常蛋疼。 并且容易错。 所以自己把 第四维 w 去掉 和 背包差不多吧。 就好写了很多。
思路应该是 从底下 往 上面 转移比较好。 因为 这样到了最上面 很容易就可以判断出是 从哪个数字开始往下走的。
由于自己思维比较习惯 从上往下转移。 就把 对应行的数都换过来就好了。 d【i】【j】【k】 代表 到了 i j 这个格子 和 为 k 有多少种方法。
还有在遍历 k的时候 要注意 k 最大就是 351. 因为 这个沙漏 最高39层。 数字最大 是 9 那么和 最大就是 391. 但是 方法很多。
自己在WA了一次之后 写了一个 39 行 全是 9的 样例。 遍找出了 错误。 在这种情况下。 可能的情况是 274877906944 种情况。 需要用到longlong
打印路径就简单点了。 肯定根据状态转移方程 递归写。 从最开始的位置 能往左 尽量往左 这样可以保证 字典序最小。 实在不行再往右。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
using namespace std;
#define ll long long
#define maxn 1000+10
#define INF 1<<30
int wh[60][30];
ll d[41][21][400];
int n,sum;
void print_path(int i, int j, int ss){
if(i == 0)
return ;
if(i > n){
if(d[i-1][j][ss-wh[i][j]]){
printf("L");
print_path(i-1,j,ss-wh[i][j]);
}
else if(d[i-1][j+1][ss-wh[i][j]]){
printf("R");
print_path(i-1,j+1,ss-wh[i][j]);
}
}
if(i <= n){
if(d[i-1][j-1][ss-wh[i][j]]){
printf("L");
print_path(i-1,j-1,ss-wh[i][j]);
}
else if(d[i-1][j][ss-wh[i][j]]){
printf("R");
print_path(i-1,j,ss-wh[i][j]);
}
}
}
int main (){
while(scanf("%d%d",&n,&sum) != EOF){
if(n == 0 && sum == 0)
break;
memset(wh,-1,sizeof(wh));
memset(d,0,sizeof(d));
for(int i = 1; i <= n; i++)
for(int j = i; j <= n; j++)
scanf("%d",&wh[i][j]);
for(int i = n+1; i <= 2*n-1; i++)
for(int j = 2*n-i; j <= n; j++)
scanf("%d",&wh[i][j]);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
swap(wh[i][j],wh[2*n-i][j]);
if(sum > 351){
printf("0\n\n");
continue;
}
for(int i = 1; i <= n; i++){
d[1][i][wh[1][i]] = 1;
}
for(int i = 2; i <= n; i++){
for(int j = 1; j <= n; j++){
if(wh[i][j] == -1)
continue;
if(wh[i-1][j-1] != -1){
for(int k = 0; k <= 360; k++){
if(d[i-1][j-1][k]){
if(k+wh[i][j] > sum)
break;
else
d[i][j][k+wh[i][j]] += d[i-1][j-1][k];
}
}
}
if(wh[i-1][j] != -1){
for(int k = 0; k <= 360; k++){
if(d[i-1][j][k]){
if(k+wh[i][j] > sum)
break;
else
d[i][j][k+wh[i][j]] += d[i-1][j][k];
}
}
}
}
}
for(int i = n+1; i <= 2*n-1; i++){
for(int j = 1; j <= n; j++){
if(wh[i][j] == -1)
continue;
if(wh[i-1][j] != -1){
for(int k = 0; k <= 360; k++){
if(d[i-1][j][k]){
if(k+wh[i][j] > sum)
break;
else
d[i][j][k+wh[i][j]] += d[i-1][j][k];
}
}
}
if(wh[i-1][j+1] != -1){
for(int k = 0; k <= 360; k++){
if(d[i-1][j+1][k]){
if(k+wh[i][j] > sum)
break;
else
d[i][j][k+wh[i][j]] += d[i-1][j+1][k];
}
}
}
}
}
ll ans = 0;
int w = -1;
int x,y;
for(int i = 1; i <= n; i++){
ans += d[2*n-1][i][sum];
if(ans != 0 && w == -1){
w = i-1;
x = 2*n-1;
y = i;
}
}
printf("%lld\n",ans);
if(ans){
printf("%d ",w);
print_path(x,y,sum);
}
printf("\n");
}
return 0;
}