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

来源:互联网 发布:最贵的域名 编辑:程序博客网 时间:2024/05/02 01:53

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


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


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

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

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

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

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

详见代码:

#include <cstdio>#include <algorithm>#include <cstdlib>#include <iostream>#define N 110using 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;}


0 0
原创粉丝点击