http://acm.hdu.edu.cn/showproblem.php?pid=1010
注意,这道题目是要恰好t时间到达,并不是在t时间内到达……
思路:剪枝+dfs
第一个剪枝我们可以想到,当剩下的步数大于剩下的时间的时候,狗是不能走到的; 接下来我们来第二个剪枝: 我们把map的奇偶性以01编号: 0 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 1 我们发现从0走一步一定走到1,从1走一步一定走到0。 也就是说,如果当前的狗所在的坐标与D的坐标奇偶性不一样,那么狗需要走奇数步。 同理,如果狗所在坐标与D的坐标奇偶性一样,那么狗需要走偶数步数。 也就是说,狗的坐标x、y和对2取余是它的奇偶性,Dxy和对2取余是D的奇偶性。 两个奇偶性一加再对2取余,拿这个余数去与剩下时间对2取余的余数作比较即可。 注意,在我做题的过程中,剪枝后,还发现超时现象。思考了很久,发现原来是我以前写dfs所带来的缺点……以前从没有注意,以后需要注意。
#include<iostream> #include<math.h> using namespace std; char s[10][10]; int ax,ay,bx,by,n,m,k; int t[4][2]={1,0,-1,0,0,1,0,-1},vist[10][10],flag; void dfs(int x,int y,int count) { int i,mx,my; if(x==bx&&y==by) { if(k==count) flag=1; return; } if(count>=k) return; if(s[x][y]!='X') { for(i=0;i<4;i++) { mx=x+t[i][0]; my=y+t[i][1]; if(s[mx][my]!='X'&&mx>=1&&mx<=n&&my>=1&&my<=m&&!vist[mx][my]) { vist[mx][my]=1; dfs(mx,my,count+1); vist[mx][my]=0; if(flag) //注意,在找到了目标之后,就不需要再找!以往编写dfs时,没有注意这点 return; } } } } int main() { while(scanf("%d%d%d",&n,&m,&k)>0&&(n+m+k)) { int i,count; for(i=1;i<=n;i++) { getchar(); for(int j=1;j<=m;j++) { scanf("%c",&s[i][j]); if(s[i][j]=='S') { ax=i; ay=j; } if(s[i][j]=='D') { bx=i; by=j; } } } getchar(); memset(vist,0,sizeof(vist)); if(abs(ax-bx)+abs(ay-by)>k||(ax+bx+ay+by+k)%2==1) //剪枝 { printf("NO\n"); continue; } vist[ax][ay]=1; flag=0; count=0; dfs(ax,ay,count); if(flag==1) printf("YES\n"); else printf("NO\n"); } return 0; }