首页 > 代码库 > 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,剪枝】
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。