UESTC 邱老师降临小行星(记忆化搜索)

人赢邱老师和任何男生比,都是不虚的。有一天,邱老师带妹子(们)来到了一个 N M 列平面的小行星。对于每一个着陆地点,邱老师总喜欢带着妹子这样走:假设着陆地点为 (r0,c0) ,那么他们下一步只能选择相邻格点,向四周走,即 (r01,c0) ,  (r0+1,c0) ,  (r0,c01) (r0,c0+1) 。之后的路程必须严格按照右转-前进-左转-前进-右转......的道路前行。但是由于邱老师很心疼妹子,所以崎岖的山脉不可以到达。当不能前进时必须要原路返回。如下图。

妹子还是邱老师会泡

问,邱老师在哪里着陆可以游历这颗星球最多的土地,输出可能访问到的最多的格点数。

Input

第一行一个整数 T 0<T20 ,表示输入数据的组数。
对于每组数据,第一行有两个整数 N M ,分别表示行数和列数, 0<N,M1000
下面 N 行,每行 M 个字符( 0 1 )。
1 代表可到达的地方, 0 代表山脉(不可到达的地方)。

Output

对于每一组数据,输出一个整数后换行,表示选择某点着陆后,可能访问到的最多的格点数。

Sample input and output

Sample Input Sample Output
2
4 3
111
111
111
111
3 3
111
101
111
10
4
记忆化搜索,每个格子对应4种形态(4个方向),每个方向又有2种状态(方式),故共有8种状态.利用一个数组,保存该格子的方向走法的能到达最多的格子数,避免重复计算。

#include <iostream>
#include <string.h>
using namespace std;
char map[1010][1010];
int dp[1010][1010][4][2]; //保存已算出结果的数组
int t,n,m;
int dfs(int x,int y,int dir,int turn)
{
    int ans=0;
    if (x>=0 && x<n && y>=0 && y<m && map[x][y]=='1')
    {
        if (dp[x][y][dir][turn]!=-1)
            return dp[x][y][dir][turn];
        if (dir==0)  //上
        {
            if (turn==1) //上右 0 1
                ans=dfs(x-1, y, 0, 0)+1; //走上上
            else  //上上 0 0
                ans=dfs(x, y+1, 0, 1)+1; //走上右
        }
        else if(dir==1) //右
        {
            if (turn==0) //右右 1 0
                ans=dfs(x+1, y, 1, 1)+1; //走右下
            else  //右下 1 1
                ans=dfs(x, y+1, 1, 0)+1;//走右右
        }
        else if(dir==2)  //下
        {
            if (turn==1) //下左 2 1
                ans=dfs(x+1, y, 2, 0)+1; //走下下
            else  //下下 2 0
                ans=dfs(x, y-1, 2, 1)+1;//走下左
        }
        else if(dir==3) //左上
        {
            if (turn==1) //3 1
                ans=dfs(x, y-1, 3, 0)+1; //走左左
            else  //左左 3 0
                ans=dfs(x-1, y, 3, 1)+1; //走左上
        }
    }
    if(x>=0 && x<n && y>=0 && y<m)
        return dp[x][y][dir][turn]=ans;
    return 0;
    
}


int main()
{
    scanf("%d",&t);
    
    while (t--)
    {
        scanf("%d%d",&n,&m);
        //n=1000,m=1000;
        
        getchar();
        for (int i=0; i<n; i++)
        {
            scanf("%s",map[i]);
        }
       // memset(map, '1', sizeof(map));
        memset(dp, -1, sizeof(dp));
        int ans=0;
        for (int i=0; i<n; i++)
        {
            for (int j=0; j<m; j++)
            {
                
                if (map[i][j]=='1')
                {
                    
                    int temp=1;
                    temp+=dfs(i-1,j,0,0);//上
                    
                    temp+=dfs(i,j+1,1,0);//右
                    
                    temp+=dfs(i+1,j,2,0);//下
                    
                    temp+=dfs(i,j-1,3,0);//左
                    if (temp>ans)
                        ans=temp;
                    
                }
            }
        }
        printf("%d\n",ans);
    }
    
    return 0;
}












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值