为了方便打印路径,考虑从下往上转移。dp[i][j][S]表示在i行j列总和为S的方案,
dp[i][j][S] = dp[i+1][left][S-x]+dp[i+1][right][S-x]
方案O(2^2*n-1),结果要用long long保存。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 22,maxs = 501; int hg[maxn<<1][maxn]; ll dp[maxn<<1][maxn][maxs]; //#define LOCAL int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif int n, S; while(scanf("%d%d", &n, &S) ,n){ int rc = 0; for(int i = n; i > 1; i--){ int *h = hg[rc++]; for(int j = 1; j <= i; j++){ scanf("%d",h+j); } } for(int i = 1; i <= n; i++){ int *h = hg[rc++]; for(int j = 1; j <= i; j++){ scanf("%d",h+j); } } rc--; memset(dp,0,sizeof(dp)); for(int j = 1; j <= n; j++){ dp[rc][j][hg[rc][j]] = 1; } while(rc>=n){ for(int j = 1, mj = (rc-- + 1) - n; j <= mj; j++){ int x = hg[rc][j]; ll *f = dp[rc][j]; for(int s = S-x; s >= 0; s--){ f[s+x] = dp[rc+1][j][s]+dp[rc+1][j+1][s]; } } } for(int i = 2; rc--,i <= n; i++){ for(int j = 1; j <= i; j++){ int x = hg[rc][j]; ll *f = dp[rc][j]; for(int s = S-x; s >= 0; s--){ f[s+x] = dp[rc+1][j-1][s]+dp[rc+1][j][s]; } } } ll ans = 0; int index = 0; for(int j = 1; j <= n; j++){ if(dp[0][j][S]){ ans += dp[0][j][S]; if(!index) index = j; } } printf("%lld ",ans); if(ans){ int j = index, s = S ; printf("%d ",j-1); rc = n; for(int i = 1; i < rc; i++){ s -= hg[i-1][j]; if(dp[i][j-1][s]){ putchar('L'); j--; }else { putchar('R'); } } rc = 2*n-1; for(int i = n; i < rc; i++){ s -= hg[i-1][j]; if(dp[i][j][s]){ putchar('L'); }else { j++; putchar('R'); } } } puts(""); } return 0; }