[HDU1010] Tempter of the Bone
题目参见:http://acm.hdu.edu.cn/showproblem.php?pid=1010
题目大意呢,就是一只doge要从S出发正好走T步到达终点D,注意不是T步之内(这不科学)求doge是否能够跑走
看上去就是一搜索题,这里我们讲三种方法
1. DFS+剪枝
DFS好不好打?好打!那就用DFS!
可是当你打完DFS提交上去发现了Time Limit Exceeded
看上去本题没什么剪枝的啊
其实是有的
既然狗要在正好T步走到D,那么,我们判断下S与D的曼哈顿距离p,再把这个p与T进行比较,如果奇偶性不同,就达不到
= =看上去很有道理?其实就很有道理。
这么剪枝,过了!
贴代码
#include<iostream> #include<stdio.h> #include<string.h> #include<stdlib.h> #include<cmath> using namespace std; int n,m,k; char map[10][10]; bool vis[10][10]; int dx[]={1,-1,0,0}; int dy[]={0,0,1,-1}; bool flag=0; int endx,endy; bool check(int x, int y) { if (x>=1 && x<=n && y>=1 && y<=m && !vis[x][y] && map[x][y]!='X') return true; return false; } void newer() { // memset(map,0,sizeof(map)); memset(vis,0,sizeof(vis)); flag=0;endx=0;endy=0; } void dfs(int step,int x,int y) { //if(flag) return; //if(step>k+1) return; if(step==k+1) { if(x==endx&&y==endy) flag=1; return; } for (int i=0;i<4;++i) { int xx=x+dx[i],yy=y+dy[i]; if(check(xx,yy)) { vis[xx][yy]=1; dfs(step+1,xx,yy); if(flag) return; vis[xx][yy]=0; } } } int main() { while(~scanf("%d%d%d",&n,&m,&k)) { if(n==0&&m==0&&k==0) break; //printf("%d%d%d",n,m,k); newer(); for (int i=1;i<=n;++i) { getchar(); for(int j=1;j<=m;++j) scanf("%c",&map[i][j]); } int walls=0,startx,starty; for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) { if(map[i][j]=='X') walls++; if(map[i][j]=='S') {startx=i;starty=j;} if(map[i][j]=='D') {endx=i;endy=j;} } getchar(); if(abs(startx-endx)+abs(starty-endy)>k||(starty+endy+startx+endx+k)%2==1) { printf("NO\n"); continue; } if(n*m-walls<k) {printf("NO\n");continue;} vis[startx][starty]=1; dfs(1,startx,starty); if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }
楼主的代码风格有点丑- -我得承认这点
2. BFS
dxy巨巨看到我DFS打跪了就鼓动我打BFS,可惜我懒,于是就想出来了上面那个剪枝。
话说肯定有人打BFS,BFS应该不会TLE的,读者有兴趣可自己尝试下。
3. DP
wyh巨巨看到dxy巨巨鼓动我打BFS,就来鼓动我打DP了
看上去确实能DP
f[k][x][y]表示第k步能否走到[x,y]
那么状态转移方程就很好列了,判断上下左右四次就结束了
看上去真的很有道理
但是因为楼主太懒,也懒得写了,于是就把DFS剪枝想出来了
好了吐槽完了,谢谢各位看官!
这篇文章由TonyFang发布。
所有解释权归TonyFang所有。
Mailto: tony-fang@map-le.net