题意: 给一个漏斗形状的矩阵,让你从最上面走到最下面,问有几种走法。并打印下标最小路径。
解法: 设dp[i][j]为走到第i行j列时有几种走法。简单DP一下就可以得到,对于要求的下标最小路径,我们可以在DP时从最下方递推上来,然后就可以很方便的从最上方一遍递推找出要求的路径了。
这道题本身不难,但是需要考虑每一个下标的细节,然后打印路径实在是恶心啊,瞬间身心俱疲。
/* **********************************************
Author : Nero
Created Time: 2013-8-26 2:12:08
Problem id : UVA 10564
Problem Name: Paths through the Hourglass
*********************************************** */
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define REP(i,a,b) for(int i=(a); i<(int)(b); i++)
#define clr(a,b) memset(a,b,sizeof(a))
typedef long long lld;
int x[42][22];
lld dp[42][22][400];
int n,m;
int main() {
while(~scanf("%d%d", &n, &m), n || m) {
clr(dp, 0);
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= n-i+1; j ++) scanf("%d", &x[i][j]);
}
for(int i = n+1; i <= 2*n-1; i ++) {
for(int j = 1; j <= i-n+1; j ++) scanf("%d", &x[i][j]);
}
if(m > 9 * (2*n-1)) {
printf("0\n\n");
continue;
}
for(int i = 1; i <= n; i ++) dp[2*n-1][i][x[2*n-1][i]] = 1;
for(int i = 2*n-2; i >= n; i --) {
for(int j = 1; j <= i-n+1; j ++) {
for(int k = x[i][j]; k <= m; k ++) {
dp[i][j][k] += dp[i+1][j][k-x[i][j]] + dp[i+1][j+1][k-x[i][j]];
}
}
}
for(int i = n; i >= 2; i --) {
for(int j = 1; j <= n-i+1; j ++) {
for(int k = 0; k <= m; k ++) {
if(k+x[i-1][j] <= m) dp[i-1][j][k+x[i-1][j]] += dp[i][j][k];
if(k+x[i-1][j+1] <= m) dp[i-1][j+1][k+x[i-1][j+1]] += dp[i][j][k];
}
}
}
lld ans = 0;
for(int i = 1; i <= n; i ++) ans += dp[1][i][m];
printf("%lld\n", ans);
for(int j = 1; j <= n; j ++) if(dp[1][j][m]) {
printf("%d ", j-1);
for(int i = 1; i < n; i ++) {
if(dp[i+1][j-1][m-x[i][j]]) {
printf("L");
m -= x[i][j];
j --;
}
else {
printf("R");
m -= x[i][j];
}
}
for(int i = n; i < 2*n-1; i ++) {
if(dp[i+1][j][m-x[i][j]]) {
printf("L");
m -= x[i][j];
}
else {
printf("R");
m -= x[i][j];
j ++;
}
}
break;
}
printf("\n");
}
return 0;
}