您的位置:首页 > 其它

hdu1010 DFS和剪枝

2014-04-13 16:26 375 查看
不剪枝的话会超时。。

#include <iostream>
#include <cmath>
#include<cstdio>
using namespace std;

int N, M ,T;
char map[10][10];
int dx,dy;
bool can;
int dir[4][2] = {{0,-1},
{0,1},
{1,0},
{-1,0}
};

void dfs(int x,int y,int t)
{
//if(x < 0 || y< 0 || x >= N || y >= M)return;//越界则返回  也可以不判断 因为在进行dfs之前都确定了是不会越界的数
if(T == t && x == dx && y ==dy)//找到出口则返回
{
can = true;
return;
}
for(int i = 0;i < 4;i++)//四个方向分别进行搜索
{
int a ,b;
a = x + dir[i][0];
b = y + dir[i][1];

if(map[a][b] != 'X' && a>= 0 && a < N && b >= 0 && b < M)//这里已经判断了是否会越界
{
map[a][b] = 'X';//把当前要走的下一个点标记为不可走的点 因为已经走过的点是不能在走的
dfs(a,b,t + 1);//按照dir中的方向继续递归下去
if(can)return;//找到出路了
map[a][b] = '.';//回朔回去
}
}
return;
}

int main()
{
int dot,sx,sy;

//    freopen("data.txt","r",stdin);
//    freopen("out.txt","w",stdout);
while(cin>>N>>M>>T,N||M||T)
{
dot = 0;
for(int i = 0; i < N; i++)
for(int j = 0; j < M; j++)
{
cin>>map[i][j];
if(map[i][j] == 'S')
{
sx = i;
sy = j;
}
else if(map[i][j] == 'D')
{
dx = i;
dy = j;
}
else if(map[i][j] == '.')dot++;
}
if(T > dot)
{
cout<<"NO"<<endl;
continue;
}
can = false;//对于很多数据的输入 最好不要在变量声明的时候付初值 经常忘了再新的测试数据前初始化。。。
map[sx][sy] = 'X';//从起点开始走 并把已经走过的起点标记为不可走
dfs(sx,sy,0);//走的步数t从0开始计数
if(can)cout<<"YES"<<endl;
else cout<<"NO"<<endl;

}
//    fclose(stdin);
//    fclose(stdout);
return 0;
}



加上剪枝以后是这样的

#include <iostream>
#include <cmath>
#include<cstdio>
#include<cstdlib>

using namespace std;

int N, M ,T;
char map[10][10];
int dx,dy;
bool can;
int dir[4][2] = {{0,-1},
{0,1},
{1,0},
{-1,0}
};

void dfs(int x,int y,int t)
{
//if(x < 0 || y< 0 || x >= N || y >= M)return;//越界则返回  也可以不判断 因为在进行dfs之前都确定了是不会越界的数
if(T == t && x == dx && y ==dy)//找到出口则返回
{
can = true;
return;
}

//if((T -t) % 2 != (abs(dx - x) + abs(dy - y)) % 2)return;
int tem ;
tem = (T - t) - abs((dx - x)) - abs((dy - y));//剩余时间 减去还需要走的步数 不够的话肯定到不了
if(tem < 0 || tem % 2 != 0)return;
//tem &1是奇偶判断 如果剩余时间 和要走的步数同奇偶的话 就有可能到达 
//不同奇偶的话 一定到不了 可以参考下面的 ppt 就知道为什么了
//另外 a b同奇偶 则 a - b 比为偶数 否则为奇数

for(int i = 0;i < 4;i++)//四个方向分别进行搜索
{
int a ,b;
a = x + dir[i][0];
b = y + dir[i][1];

if(map[a][b] != 'X' && a>= 0 && a < N && b >= 0 && b < M)//这里已经判断了是否会越界
{
map[a][b] = 'X';//把当前要走的下一个点标记为不可走的点 因为已经走过的点是不能在走的
dfs(a,b,t + 1);//按照dir中的方向继续递归下去
if(can)return;//找到出路了
map[a][b] = '.';//回朔回去
}
}
return;
}

int main()
{
int dot,sx,sy;

//    freopen("data.txt","r",stdin);
//    freopen("out.txt","w",stdout);
while(cin>>N>>M>>T,N||M||T)
{
dot = 0;
for(int i = 0; i < N; i++)
for(int j = 0; j < M; j++)
{
cin>>map[i][j];
if(map[i][j] == 'S')
{
sx = i;
sy = j;
}
else if(map[i][j] == 'D')
{
dx = i;
dy = j;
dot++;//忘了再这里加一 总是WA 哎 因为最后一个D 也要走一步才能到
}
else if(map[i][j] == '.')dot++;
}
if(T > dot)
{
cout<<"NO"<<endl;
continue;
}
can = false;//对于很多数据的输入 最好不要在变量声明的时候付初值 经常忘了再新的测试数据前初始化。。。
map[sx][sy] = 'X';//从起点开始走 并把已经走过的起点标记为不可走
dfs(sx,sy,0);//走的步数t从0开始计数
if(can)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;

}
//    fclose(stdin);
//    fclose(stdout);
return 0;
}



感受了一下DFS

主要在  数据初始化  和 dot 加一那个地方检查了很久才发现。。。


方向数组只要四个方向走到了就可以 不用在意顺序 顺序有时候会影响执行时间 但总体上应该不会超时吧

参考PPT19页

参考博客
2 3 4
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: