题目 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行的程序。
还要加上剪枝的功能!