HDU - 1208Pascal's Travels(记忆化搜索相关练习1)

知识共享许可协议 版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons

题目链接:https://cn.vjudge.net/contest/306123#problem/A
题目解析 地图为n*n,从左上角走到右下角,只能向右和向下,遇到括号里的数字是几就走几步,0除外(0是一个死胡同,不能走了),求有几种方法?
下图很好的说明了从起点到终点的路径
在这里插入图片描述
注: 地图也是相当大的,若一个一个搜,容易超时,就需要优化----->把搜过的点的数据保留下来,下一次搜到这一点的时候直接用保留下来的数据。避免了重复操作(专业术语:记忆化搜索)。把每一点的状态保留下来,说明了此搜索与dp密不可分。

对于这道题的细节
(1)调用dfs时,long long每次都要写。
(2)这道题只能往右和往下,这道题对坐标的处理也是需要积累的。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long s;
int to[2][2]={1,0,0,1},n;
long long dp[50][50];//dp[i][j]:记录(i,j)到终点的路径
char a[50][50];
long long  dfs(int x,int y){
    int flag=0;
    long long s=0;//这个地方long long必须写,可能数据过大,题目中大致可能也是这个意思
    if(dp[x][y]!=-1)
        return dp[x][y];
    if(x==n-1&&y==n-1) //目标状态
        return 1; //路径加1
    if(a[x][y]=='0') {
        dp[x][y]=0; //对零的特判
        return 0;
    }
    for(int i=0; i<2; i++){
        int tx=(a[x][y]-'0')*to[i][0]+x; //下一点的坐标
        int ty=(a[x][y]-'0')*to[i][1]+y;
        if(tx>=0&&tx<n&&ty>=0&&ty<n){
            flag=1;
            s=s+dfs(tx,ty);
        }
    }//一个点搜到不能再搜了,才执行下面的if选择句
    if(flag==0)  //这一点向右和向左都无法走
    {
        dp[x][y]=0;
        return dp[x][y];
    }
    else
    {
        dp[x][y]=s;
        return dp[x][y];
    }
}
int main(){
    while(~scanf("%d",&n)) {
        if(n==-1)
            break;
        s=0;
        for(int i=0; i<n; i++) //输入地图
            scanf("%s",a[i]);
        memset(dp,-1,sizeof(dp));
        printf("%lld\n",dfs(0,0)); //dfs(0,0)为左上角
    }
    return 0;
}

不因长夜漫漫而畏惧
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lylzsx20172018/article/details/91900485