首页 > 代码库 > hdu 5024 Wang Xifeng's Little Plot【暴力dfs,剪枝】

hdu 5024 Wang Xifeng's Little Plot【暴力dfs,剪枝】

2014年广州网络赛的C题,也是水题。要你在一个地图中找出一条最长的路,这条路要保证最多只能有一个拐角,且只能为90度


我们直接用深搜,枚举每个起点,每个方向进行dfs,再加上剪枝。


但是如果直接写的话,那一定会特别麻烦,再加上方向这一属性也是我们需要考虑的方面,我们将从别的地方到当前点的方向编一个号:往右为0,如下图顺时针顺序编号

阿萨(往右下方向为1,往下为2......以此类推)

我们知道了当前点的坐标,来到当前点的方向,以及到目前有没有拐弯,这几个属性之后,就可以记忆化搜索了,用一个四维数组dp[][][][]实现。

下面,我们还需要知道从某个方向来到这个点,我们下一步能走到什么位置,比如我上次是往右来到这个点,那么我下次就只能往上或者往下,或者继续往右走。也就是说,每次其实只能走三个方向。再用一个数组记录一下这三个数字,那么代码就能缩短很长了。那怎么记录?

还是一样,我们将每个点的附近八个点分别编号,方向数组大家应该都知道吧,用一个数组加一个循环模拟八个方向的移动。有了这个数组,我们就可以很方便的记录上述所说的东西了。

详见代码:

#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <iostream>
#define N 110
using namespace std;
int n,dp[N][N][9][2],ans,dx[]= {-1,-1,-1,0,0,1,1,1},dy[]= {-1,0,1,-1,1,-1,0,1};
int D[8][3]= {{1,6,4},{2,5,7},{3,4,6},{0,7,5},{1,6,3},{2,5,0},{3,4,1},{0,7,2}};//每个方向过来,我能移动到相对当前点的哪几个点。里面的数对应方向数组的下标,每个方向对应的前两个元素代表需要转角,第三个元素代表直线移动。
int fr[8][2]= {{6,2},{7,3},{4,0},{5,1},{6,2},{7,3},{4,0},{5,1}};//代表我转角的话,到达相对当前点的那个点。
char a[N][N];
int dfs(int ix,int jx,int dir,int w)//ix,jx代表当前坐标,dir代表上一个点到这个点的方向,w代表是否已转向
{
    if(dp[ix][jx][dir][w]!=-1) return dp[ix][jx][dir][w];//记忆话搜索
    int tmp=1;//初始化为1
    for(int i=0; i<3; i++)
    {
        int u=D[dir][i];
        int x=ix+dx[u],y=jx+dy[u];
        if(x>=0 && x<n && y>=0 && y<n && a[x][y]=='.')
        {
            if(i==2)
            {
                tmp=max(tmp,dfs(x,y,dir,w)+1);
            }
            else if(w==0)
            {
                tmp=max(tmp,dfs(x,y,fr[dir][i],1)+1);
            }
        }
    }
    return dp[ix][jx][dir][w]=tmp;
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        ans=0;
        memset(dp,-1,sizeof(dp));
        for(int i=0; i<n; i++)
            scanf("%s",a[i]);
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
            {
                if(a[i][j]=='#') continue ;//遍历每个不是#的点作为起点,作为起点,所以八个方向都要遍历。
                for(int k=0; k<8; k++)
                {
                    dfs(i,j,k,0);
                }
            }
        }
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
                for(int k=0; k<8; k++)
                    for(int l=0; l<2; l++)
                        ans=max(ans,dp[i][j][k][l]);
        printf("%d\n",ans);
    }
    return 0;
}


hdu 5024 Wang Xifeng's Little Plot【暴力dfs,剪枝】