UVA 10564 - Paths through the Hourglass

来源:互联网 发布:聚划算抢购技巧知乎 编辑:程序博客网 时间:2024/06/08 05:51

这个题最初的想法是用四维数组动规  d【i】【j】【k】【w】  i j  代表 某一个位置 k 代表 到这这个 位置 的 和  w代表 从上一个格子 到这个格子的方向(1代表R 0 代表 L)


在写代码的过程中非常蛋疼。 并且容易错。 所以自己把 第四维 w  去掉 和 背包差不多吧。 就好写了很多。 


思路应该是 从底下 往 上面 转移比较好。 因为 这样到了最上面 很容易就可以判断出是 从哪个数字开始往下走的。


由于自己思维比较习惯 从上往下转移。  就把 对应行的数都换过来就好了。  d【i】【j】【k】  代表 到了 i j  这个格子 和 为 k 有多少种方法。


还有在遍历 k的时候 要注意  k 最大就是 351. 因为  这个沙漏 最高39层。 数字最大 是 9  那么和  最大就是 391. 但是 方法很多。 


自己在WA了一次之后 写了一个 39 行 全是 9的 样例。 遍找出了 错误。 在这种情况下。 可能的情况是 274877906944 种情况。 需要用到longlong 


打印路径就简单点了。 肯定根据状态转移方程 递归写。 从最开始的位置 能往左 尽量往左 这样可以保证 字典序最小。 实在不行再往右。


#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>#include <cmath>#include <cstdlib>#include <string>#include <map>#include <vector>#include <set>#include <queue>#include <stack>using namespace std;#define ll long long#define maxn 1000+10#define INF 1<<30int wh[60][30];ll d[41][21][400];int n,sum;void print_path(int i, int j, int ss){    if(i == 0)        return ;    if(i > n){        if(d[i-1][j][ss-wh[i][j]]){            printf("L");            print_path(i-1,j,ss-wh[i][j]);        }        else if(d[i-1][j+1][ss-wh[i][j]]){            printf("R");            print_path(i-1,j+1,ss-wh[i][j]);        }    }    if(i <= n){        if(d[i-1][j-1][ss-wh[i][j]]){            printf("L");            print_path(i-1,j-1,ss-wh[i][j]);        }        else if(d[i-1][j][ss-wh[i][j]]){            printf("R");            print_path(i-1,j,ss-wh[i][j]);        }    }}int main (){    while(scanf("%d%d",&n,&sum) != EOF){        if(n == 0 && sum == 0)        break;        memset(wh,-1,sizeof(wh));        memset(d,0,sizeof(d));        for(int i = 1; i <= n; i++)            for(int j = i; j <= n; j++)                scanf("%d",&wh[i][j]);        for(int i = n+1; i <= 2*n-1; i++)            for(int j = 2*n-i; j <= n; j++)                scanf("%d",&wh[i][j]);        for(int i = 1; i <= n; i++)            for(int j = 1; j <= n; j++)                swap(wh[i][j],wh[2*n-i][j]);        if(sum > 351){            printf("0\n\n");            continue;        }        for(int i = 1; i <= n; i++){            d[1][i][wh[1][i]] = 1;        }        for(int i = 2; i <= n; i++){            for(int j = 1; j <= n; j++){                if(wh[i][j] == -1)                    continue;                if(wh[i-1][j-1] != -1){                    for(int k = 0; k <= 360; k++){                        if(d[i-1][j-1][k]){                            if(k+wh[i][j] > sum)                                break;                            else                                d[i][j][k+wh[i][j]] += d[i-1][j-1][k];                        }                    }                }                if(wh[i-1][j] != -1){                    for(int k = 0; k <= 360; k++){                        if(d[i-1][j][k]){                            if(k+wh[i][j] > sum)                                break;                            else                                d[i][j][k+wh[i][j]] += d[i-1][j][k];                        }                    }                }            }        }        for(int i = n+1; i <= 2*n-1; i++){            for(int j = 1; j <= n; j++){                if(wh[i][j] == -1)                    continue;                if(wh[i-1][j] != -1){                    for(int k = 0; k <= 360; k++){                        if(d[i-1][j][k]){                            if(k+wh[i][j] > sum)                                break;                            else                                d[i][j][k+wh[i][j]] += d[i-1][j][k];                        }                    }                }                if(wh[i-1][j+1] != -1){                    for(int k = 0; k <= 360; k++){                        if(d[i-1][j+1][k]){                            if(k+wh[i][j] > sum)                                break;                            else                                d[i][j][k+wh[i][j]] += d[i-1][j+1][k];                        }                    }                }            }        }        ll ans = 0;        int w = -1;        int x,y;        for(int i = 1; i <= n; i++){            ans += d[2*n-1][i][sum];            if(ans != 0 && w == -1){                w = i-1;                x = 2*n-1;                y = i;            }        }        printf("%lld\n",ans);        if(ans){            printf("%d ",w);            print_path(x,y,sum);        }        printf("\n");    }    return 0;}




0 0
原创粉丝点击