uva10564(DP+路径打印)

来源:互联网 发布:mix软件怎么拼图 编辑:程序博客网 时间:2024/06/07 22:22

这题的意思就是给出一个沙漏,第一行的两个数字n , s ;n就是沙漏的大小,最上面一行元素的个数,s就是目标权值.

要求问从第一行到最后一行所有路径中权值为s的路劲有几条.

然后输出字典序最小那条路是从第一行哪一个位置开始的(第一个是位置0),并输出这条路.

如果没有路径,输出一个空行.

首先,我们记(i,j)这个点权值为num[i][j] ,比如我们要知道从(i,j)这个位置到最后的权值为s的路径有多少条

那么我们要知道从(i + 1 , j) 这个位置到最后权值为s - num[i][j]的路径条数.

再加上从(i+ 1 , j -   1)这个位置到最后权值为s - num[i][j]的路径条数.

那么我们设f[i][j][s] 代表 从位置(i , j)到达最后,权值为s的路径有几条.

而且容易得到状态转移方程

f[i][j][s] = dp(i + 1 , j , s - num[i][j]) + dp(i + 1 , j - 1 , s -num[i][j]);
但是有一点需要特别注意,在沙漏上半部,j 往下是 j - 1 和 j

但是在沙漏下半部,j往下 是 j 和 j +1; 所以需要判断 i < n,来决定用哪一个.

然后是要打印路径,因为要字典序最小,从左往右找到第一个可行的路径递归打印出来.

打印时只要判断往左走是否可达,可达就往左,否则往右.(保证最小)

打印时也要注意是在上半边,还是下半边:


AC代码:


#include<stdio.h>#include<string.h>#define ll long longconst int N = 50;int num[N][N];int l[N][N];int r[N][N];ll f[N][N][N * 10];int n,s,high;ll res;ll dp(int i , int j ,int s) {if(f[i][j][s] != -1)return f[i][j][s];if(num[i][j] == -1 || s < 0 )return 0;if(i == 2 * n - 1) {if(s == num[i][j])f[i][j][s] = 1;elsef[i][j][s] = 0;}else {if(i < n)f[i][j][s] = dp(i + 1 , j , s - num[i][j]) + dp(i + 1 , j - 1 , s -num[i][j]);elsef[i][j][s] = dp(i + 1 , j , s - num[i][j]) + dp(i + 1 , j + 1 , s -num[i][j]);}return f[i][j][s];}void print(int i , int j ,int s) {if(i == 2 * n -1) {printf("\n");return ;}if(i < n) {if(dp(i + 1 , j - 1, s - num[i][j]) > 0) {printf("L");print(i + 1 , j - 1 ,s - num[i][j]);}else {printf("R");print(i + 1 , j ,s - num[i][j]);}}else {if(dp(i + 1 , j, s - num[i][j]) > 0) {printf("L");print(i + 1 , j ,s - num[i][j]);}else {printf("R");print(i + 1 , j + 1 ,s - num[i][j]);}}}int main () {while(scanf("%d%d",&n,&s) && n + s) {memset(num, -1, sizeof(num));memset(f, -1 , sizeof(f));for(int i = 1; i < n; i++) {  for(int j = 1; j <= (n-i+1); j++) {  scanf("%d", &num[i][j]);  }  }  for(int i = 1; i <= n; i++) {  for(int j = 1; j <= i; j++) {  scanf("%d", &num[i+n-1][j]);  }  }  res = 0 ;for (int i = 1 ; i <= n ; i++) {res += dp(1 , i , s);}printf("%lld\n",res);if(res == 0)printf("\n");else {for (int i = 1 ; ; i++) {if(f[1][i][s] != 0) {printf("%d ",i - 1);print(1 , i , s);break;}}}}}


0 0