UVA10564- Paths through the Hourglass

来源:互联网 发布:中国农业银行软件 编辑:程序博客网 时间:2024/06/06 05:39

题意:给你一个沙漏般的数组,找出自顶向下数字相加的和为S的路径的总数。输出字典序最小。


思路:计数DP。刚开始自己从上往下算,但发现这样的话,之后的递归输出会比较麻烦。看了网上别人的思路,先进行下半部分的DP,然后在进行上半部分的DP。


下半部分状态转移:d[i][j] = d[i + 1][j] + d[i + 1][j + 1];

上半部分状态转移:当j == 1时,d[i][j] += d[i + 1][j];当 j == n - i + 1时,d[i][j] += d[i + 1][j - 1];else d[i][j] = d[i + 1][j] + d[i + 1][j - 1];


#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int INF = 0x3f3f3f3f;const int MAXN = 100;int n, s;int arr[MAXN][MAXN];long long d[MAXN][MAXN][505];void init() {    for (int i = 1; i <= n; i++)        for (int j = 1; j <= n - i + 1; j++)            scanf("%d", &arr[i][j]);    for (int i = n + 1; i <= n * 2 - 1; i++)        for (int j = 1; j <= i - n + 1; j++)            scanf("%d", &arr[i][j]);}long long dp() {    for (int i = 1; i <= n; i++)        d[n * 2 - 1][i][arr[n * 2 - 1][i]] = 1;        for (int i = n * 2 - 2; i >= n; i--)        for (int j = 1; j <= i - n + 1; j++)             for (int k = arr[i][j]; k <= s; k++) {                int temp = arr[i][j];                 d[i][j][k] = d[i + 1][j][k - temp] + d[i + 1][j + 1][k - temp];             }     long long num = 0;    for (int i = n - 1; i >= 1; i--)         for (int j = 1; j <= n - i + 1; j++) {            for (int k = arr[i][j]; k <= s; k++) {                int temp = arr[i][j];                 if (j == 1)                            d[i][j][k] += d[i + 1][j][k - temp];                else if (j == n - i + 1)                    d[i][j][k] += d[i + 1][j - 1][k - temp];                else                    d[i][j][k] = d[i + 1][j][k - temp] + d[i + 1][j - 1][k - temp];              }            if (i == 1)                num += d[i][j][s];        }    return num;        }void outPut(int x, int y, int sum) {    if (x >= n * 2 - 1)        return;    int temp = arr[x][y];     if (x < n) {        if (y > 1 && d[x + 1][y - 1][sum - temp]) {            printf("L");             outPut(x + 1, y - 1, sum - temp);            return;        }         else {            printf("R");             outPut(x + 1, y, sum - temp);              return;        }    }    else {        if (d[x + 1][y][sum - temp]) {            printf("L");             outPut(x + 1, y, sum - temp);            return;         }         else {            printf("R");             outPut(x + 1, y + 1, sum - temp);              return;        }    }}int main() {    while (scanf("%d %d", &n, &s) && n || s) {        init();             memset(d, 0, sizeof(d));        long long ans = dp();        cout << ans << endl;        for (int i = 1; i <= n; i++)             if (d[1][i][s]) {                printf("%d ", i - 1);                 outPut(1, i, s);                 break;            }        printf("\n");    }    return 0;}


0 0
原创粉丝点击