UVA 10564 - Paths through the Hourglass

来源:互联网 发布:电影票房猫眼数据 编辑:程序博客网 时间:2024/06/05 04:51

题目链接~~>

做题感悟:这题上来就暴力了一下,就过可想而知,想用过记忆划搜索但是就是为什么没想到增加一维呢??

解题思路:

                  因为到达每种状态都有许多的可以组成的值,so ~ 可以开三维的数组即:dp[ i ] [ j ] [ s ]  代表第 i 行 第 j 个 组合成 s 有多少种方法。用记忆化搜索比较好写,注意处理边界。还有一点很坑,路径条数要用 long long int 保存,因为这个错了两次。

代码:

#include<stdio.h>#include<queue>#include<cmath>#include<string.h>#include<iostream>#include<iomanip>#include<algorithm>#include<stdlib.h>#define INT long long intusing namespace std ;const int MY = 40 + 10 ;const int MX = 500 + 10 ;INT n,m,tot ;INT dp[MY][MY][MX],g[MY][MY] ;INT dy[4]={-1,0,0,1} ;char s[5]={'L','R','L','R'} ;INT DP(INT x,INT y,INT S) // 记忆化搜索{    INT st=0,ed=0 ;    if(dp[x][y][S]!=-1)        return dp[x][y][S] ;    INT& ans = dp[x][y][S] ;    if(x<=m-1)    {        st=0 ;ed=2 ;    }    else    {        st=2 ; ed=4 ;    }    INT mx=0 ;    for(INT j=st ; j<ed ;j++)    {        INT sx=x+1 ;        INT sy=y+dy[j] ;        if(S>=g[sx][sy]&&g[sx][sy]!=-1)            mx+=DP(sx,sy,S-g[sx][sy]) ;    }    return ans=mx ;}void input() // 输入处理{    n=m*2-1 ;    memset(g,-1,sizeof(g)) ;    memset(dp,-1,sizeof(dp)) ;    for(INT i=m ;i>=2 ;i--)      for(INT j=1 ;j<=i ;j++)         scanf("%lld",&g[m-i+1][j]) ;    for(INT i=m,j=1 ;i<=n ;i++,j++)      for(INT k=1 ;k<=j ;k++)        scanf("%lld",&g[i][k]) ;    for(INT i=1 ;i<=m ;i++)        dp[n][i][0]=1 ;}void print(INT x,INT y,INT S) // 递归输出{    INT st=0,ed=0 ;    if(x<=m-1)    {        st=0 ;ed=2 ;    }    else    {        st=2 ; ed=4 ;    }    for(INT i=st ;i<ed ;i++)    {        INT sx=x+1 ;        INT sy=y+dy[i] ;        if(g[sx][sy]!=-1&&S>=g[sx][sy]&&dp[sx][sy][S-g[sx][sy]]>=1)        {            cout<<s[i]  ;            print(sx,sy,S-g[sx][sy]) ;            break ;        }    }}int main(){    while(scanf("%d%d",&m,&tot),m+tot)    {        input() ;        INT best=0 ;        for(INT i=1 ;i<=m ;i++)        {            if(tot>=g[1][i])                 dp[1][i][tot]=DP(1,i,tot-g[1][i]) ;           if(dp[1][i][tot]>0)               best+=dp[1][i][tot] ;        }        cout<<best<<endl ;        if(best)         for(INT i=1 ;i<=m ;i++)           if(dp[1][i][tot]>=1)           {              cout<<i-1<<" " ;              print(1,i,tot-g[1][i]) ;              break ;           }        cout<<endl ;    }    return 0 ;}


0 0