hdoj--1010<dfs+奇偶剪枝>

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010

题目描述:在n*m的矩阵中,有一起点和终点,中间有墙,给出起点终点和墙,并给出步数,在该步数情况下走到终点,走过的点不能再走;

题目要点:dfs+奇偶剪枝;输入;

      本题用dfs可以做出结果,但是会超时,需要用到就剪枝,来减去大部分的可能;

奇偶剪枝:

      方格中起点(tx,ty)和终点(dx, dy)最小步骤是minstep=abs(tx-dx)+abs(ty-dy);

      给定步数t,从起点走到终点,如果t < minstep,不可以,如果t =minstep,一部也没有多走,如果t> minstep,则多走了extra步,extra=t-minstep;

     经过推导可以证明多走的一定是偶数步,即extra一定是偶数。

      现在,如果已经走了n步,到达了(x,y)的位置,现在距离终点最小距离是L=abs(x-dx)+abs(y-dy);  现在还可以走的是 t - n 步,如果(t-n)<0,则不能走到地方,如果(t- n)-L 是奇数,则无法多走出偶数步到达指定位置,所以这样的是不行的;

       同时,本题时间卡的比较紧,使用dfs事实上是构造可行方案树,有m步最后就有2^m个叶子,所以在进入下一层dfs之前判断是否可行可以减少一大部分叶子;

代码如下:

 1 
 2 #include<iostream>
 3 #include<math.h>
 4 
 5 using namespace std;
 6 int n,m,t,k,dx,dy;
 7     int p,q,tm;
 8     int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};//构建位置数组,遍历周围四个点;
 9 char a[8][8];
10 void dfs(int x,int y,int count)
11 {
12     int temp;
13     temp=t-count-abs(dx-x)-abs(dy-y);
14     if(temp<0||temp%2==1)                    //判断是否有偶数步,没有就退出;
15         return ;
16 
17     int tx,ty;
18         for(int i=0;i<4;i++)                 //循环遍历周围的四个结点,先预判是否超出边界,然后判断是否找到结果,如果找到就不用在进去了;
19         {
20             tx=x+dir[i][0];
21             ty=y+dir[i][1];
22             if(a[tx][ty]=='D'&&count==t-1)
23             {
24                 k=1;
25                 return ;
26             }
27             if(a[tx][ty]=='.'&&(tx>=0&&tx<n)&&(ty>=0&&ty<m))
28             {
29                 a[tx][ty]='X';
30                 dfs(tx,ty,count+1);
31                 a[tx][ty]='.';
32                 if(k==1)           //如果没有确定的结果就进去dfs,出来后判断是否有结果了,这样可以减少dfs的步骤;
33                     return ;
34             }
35         }
36     
37 }
38 int main()
39 {
40     while(cin>>n>>m>>t&&n!=0||m!=0||t!=0)
41     {
42         tm=0;
43         for(int i=0;i<n;i++)
44         {
45             for(int j=0;j<m;j++)
46             {
47                 cin>>a[i][j];
48                 if(a[i][j]=='S')
49                 {
50                     p=i;q=j;
51                 }
52                 if(a[i][j]=='D')
53                 {
54                     dx=i;dy=j;
55                 }
56                 if(a[i][j]=='X')
57                     tm++;
58             }
59         }
60         k=0;
61         if(n*m-tm<=t)     //开始判断是否有足够的空来走,没有就直接跳过dfs;
62         {
63             printf("NO
");
64             continue;
65         }
66         dfs(p,q,0);
67         if(k==1)
68             printf("YES
");
69         else
70             printf("NO
");
71     }
72     return 0;
73 }
View Code

顺便贴几个dfs的题目

hdoj:  1010  1015  1016  1045  1175  1181  1241  1272  1421  1455  1518  1728

原文地址:https://www.cnblogs.com/by-1075324834/p/4328758.html