DFS程序

题目 https://www.luogu.org/problemnew/show/P2802

以下两个算法,对这组数据的结果不同,待查找原因

9 9
0 0 1 0 2 1 1 4 1
1 1 1 0 1 1 4 4 1
1 1 1 1 4 4 4 1 4
0 0 1 0 1 0 0 4 1
1 1 0 0 1 4 1 1 4
1 0 0 0 1 1 0 1 1
1 1 0 0 1 0 4 1 1
1 1 0 0 1 1 0 1 4
1 3 1 1 4 0 0 1 1

以下数据速度慢,需要剪枝!

9 9
1 0 1 1 1 1 1 4 1
1 4 1 1 1 1 1 1 1
4 0 4 1 0 1 1 1 0
4 4 3 4 1 4 1 1 1
0 4 1 4 1 1 4 4 1
1 1 1 1 1 1 1 4 0
1 1 1 1 1 4 1 1 0
1 1 1 4 4 4 4 0 0
1 1 1 2 4 1 1 4 1

 

#include <bits/stdc++.h>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <cstring>
#include <time.h> 

using namespace std;

using std :: min;

int map1[10][10],n,m,Min = 9999999;
bool vis[10][10];


int x,y,t1;
int a[15][15],tr[15][15];
int move[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
 
 
 
void dfsOK(int x,int y,int tot,int now) {
  if (!now || !map1[x][y] || !vis[x][y]) return;   //没有生命,或者(x,y)是障碍物,或者已走过此路
  if (x < 1 || x > n || y < 1 || y > m) return;   //出界
  if (tot > Min) return;   //剪枝
  if (map1[x][y] == 3) {   //到达终点
    Min = min(tot,Min); 
    return;
  }
  int now1 = now-1;
  if (map1[x][y] == 4) now1 = 5; //加生命
  vis[x][y] = false;   //标记已走过
  //printf("%d,%d %d\n",x,y,tot);
  dfsOK(x-1,y,tot+1,now1);   //上
  dfsOK(x+1,y,tot+1,now1);  //下
  dfsOK(x,y-1,tot+1,now1);   //左
  dfsOK(x,y+1,tot+1,now1);  //右
  vis[x][y] = true;   //还原
}
int mainOK() {
  int x,y;
  
  freopen("a.txt","r",stdin);
  scanf("%d%d",&n,&m);
  memset(vis,true,sizeof(vis));
  Min=9999999;
  for (int i = 1;i <= n;i++)
    for (int j = 1;j <= m;j++) {
          scanf("%d",&map1[i][j]);
      if (map1[i][j] == 2) x = i,y = j;   //记下起点
      }
  dfsOK(x,y,0,6);
  if (Min == 9999999) Min=-1;
  printf("%d",Min);
  return Min;
}


///



int dfs(int x1,int y1,int xue)
{
	int i,x2,y2,ans=100000,t;
	
	if (xue==0)
		return -1;
	if (a[x1][y1]==3)
		return 0;
		
	for (i=0;i<4;i++)
	{
		x2=x1+move[i][0];
		y2=y1+move[i][1];
		if (x2<0 || y2<0 || x2>=n || y2>=m)
			continue;
		if (a[x2][y2]==0 || tr[x2][y2]!=0)
			continue;
		else if (a[x2][y2]==4)
			xue=6;
		tr[x2][y2]=1;
		t=dfs(x2,y2,xue-1);
		tr[x2][y2]=0;
		if (t!=-1)
			ans=min(ans,t+1);
	}
	if (ans==100000)
		return -1;
	return ans;
}//
 
int main2()
{
	int i,j;
	
	freopen("a.txt","r",stdin);
	scanf("%d%d",&n,&m);
	for (i=0;i<n;i++)
	{
		for (j=0;j<m;j++)
		{
			scanf("%d",&a[i][j]);
			if (a[i][j]==2)
			{
				x=i;
				y=j;
			}
		}
	}
	memset(tr,0,sizeof(tr));
	tr[x][y]=1;
	t1=dfs(x,y,6);
	printf("%d",t1);
		
	return t1;
}


int MakeData()
{
	freopen("a.txt","w",stdout);
	int i,j,n,m,a[10][10],t;
	
	srand((unsigned)time(0)); 
	n=9; m=9;
	for(i=0;i<n;i++)
		for(j=0;j<m;j++)
		{
			t=rand()%10;
			if(t>=8)
				a[i][j]=4;
			else if(t<=1)
				a[i][j]=0;
			else
				a[i][j]=1;
		}
	//一个2,一个3, 
	a[rand()%n][rand()%m]=2;
	a[rand()%n][rand()%m]=3;
	printf("%d %d\n",n,m);
	for(i=0;i<n;i++)
	{
		for(j=0;j<m;j++)
			printf("%d ",a[i][j]);
		printf("\n");
	}
	fclose(stdout);
	freopen( "CON", "w", stdout );
}


int main()
{
	int ans1,ans2;
	while(1)
	{
		//MakeData();
		ans1=mainOK();printf(" ");
		ans2=main2();printf("\n");
		if(ans1!=ans2) 
			break;
	}
	
}

原因已经找到:xue的值处理问题!当上一个点的xue为1下一点即使为4也不能复活!

修改80,81行的程序。

 

还要加上剪枝的功能!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值