题意:给定沙漏,每个格子对应一个数,求给定路径权值和的路径条数即最小起点,最小字典序的路径。
思路:有数据范围可定义状态dp(i,j,k)表示第i行第j个格子到达终点的权值和为k的路径条数,那么
对于倒三角:dp(i,j,k)=dp(i+1,j-1,k-e[i][j])+dp(i+1,j,k-e[i][j]);
对于正三角:dp(i,j,k)=dp(i+1,j,k-e[i][j])+dp(i+1,j+1,k-e[i][j]);
输出路径可以用递归或者直接迭代。
#include <iostream>
#include <cstring>
using namespace std;
long long dp[45][25][355];
int e[45][25];
int main()
{
int n,s;
while(cin>>n>>s&&(s+n)){
// 读入及初始化
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
for(int j=1;j<=(n-i+1);j++) cin>>e[i][j];
for(int i=2;i<=n;i++)
for(int j=1;j<=i;j++) cin>>e[i+n-1][j];
for(int i=1;i<=n;i++) dp[(n<<1)-1][i][e[(n<<1)-1][i]]=1;
// dp求解
for(int i=2*n-2;i>=n;i--)
for(int j=1;j<=i-n+1;j++)
for(int k=e[i][j];k<=s;k++)
dp[i][j][k]=dp[i+1][j][k-e[i][j]]+dp[i+1][j+1][k-e[i][j]];
for(int i=n-1;i>=1;i--)
for(int j=1;j<=n-i+1;j++)
for(int k=e[i][j];k<=s;k++)
dp[i][j][k]=dp[i+1][j-1][k-e[i][j]]+dp[i+1][j][k-e[i][j]];
// 输出结果
long long total=0,ps=-1;
for(int i=1;i<=n;i++) if(dp[1][i][s]){
total+=dp[1][i][s];
if(ps==-1) ps=i;
}
if(!total){
cout<<0<<endl<<endl;
continue;
}
cout<<total<<endl;
cout<<ps-1<<' ';
for(int i=1;i<n;i++){
s-=e[i][ps];
if(dp[i+1][ps-1][s]){
cout<<'L';
ps--;
}
else cout<<'R';
}
for(int i=n;i<2*n-1;i++){ //i+n-1
s-=e[i][ps];
if(dp[i+1][ps][s]) cout<<'L';
else{
cout<<'R';
ps++;
}
}
cout<<endl;
}
return 0;
}