洛谷 题解 P2802 【回家】
思路:DFS+剪枝
本题可以用一个字符二维数组来存整个地图,然后在往四个方向进行搜索。注意:当走到家门前要先判断血量!(本人就被坑了)
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int n,m;
int Begin_x,Begin_y,End_x,End_y;
int ans=0x7ffffff;
char Map[N][N];
bool t[N][N];
int dx[5]={0,1,-1,0,0},dy[5]={0,0,0,1,-1};
int sm=6;
inline void dfs(int x,int y,int tot)
{
bool four=false;
if(x==End_x&&y==End_y&&sm>0)
{
ans=min(ans,tot);
return;
}
for(int i=1;i<=4;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a>0&&b>0&&a<=n&&b<=m&&(sm-1>0||Map[a][b]=='4')&&Map[a][b]!='0'&&!t[a][b])
{
sm--;
t[x][y]=true;
if(Map[x][y]=='4')sm=6,four=true,Map[x][y]='1';
dfs(a,b,tot+1);
sm++;
t[x][y]=false;
if(four)Map[x][y]='4';
}
}
}
inline int read()
{
int tot=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
tot=tot*10+c-'0';
c=getchar();
}
return tot*f;
}
int main()
{
n=read();
m=read();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>Map[i][j];
if(Map[i][j]=='2')Begin_x=i,Begin_y=j;
else if(Map[i][j]=='3')End_x=i,End_y=j;
}
}
//cout<<Begin_x<<" "<<Begin_y<<endl<<End_x<<" "<<End_y<<endl;
dfs(Begin_x,Begin_y,0);
if(ans==0x7ffffff)cout<<-1<<endl;
else cout<<ans<<endl;
return 0;
}
信心满满地提交,什么?90分??!
下了第九个测试点,发现小H栽死在家门口了。
修改了半天,改成了这样:
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int n,m;
int Begin_x,Begin_y,End_x,End_y;
int ans=0x7ffffff;
char Map[N][N];
bool t[N][N];
int dx[5]={0,1,-1,0,0},dy[5]={0,0,0,1,-1};
int sm=6;
inline void dfs(int x,int y,int tot)
{
bool four=false;
if(sm<=0||tot>=ans)return;
if(x==End_x&&y==End_y)
{
//cout<<sm<<" "<<tot<<endl;
ans=min(ans,tot);
return;
}
for(int i=1;i<=4;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a>0&&b>0&&a<=n&&b<=m&&Map[a][b]!='0'&&!t[a][b])
{
sm--;
t[x][y]=true;
if(Map[x][y]=='4')sm=6,four=true,Map[x][y]='1';
dfs(a,b,tot+1);
sm++;
t[x][y]=false;
if(four)Map[x][y]='4',sm-=6;
}
}
}
inline int read()
{
int tot=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
tot=tot*10+c-'0';
c=getchar();
}
return tot*f;
}
int main()
{
n=read();
m=read();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>Map[i][j];
if(Map[i][j]=='2')Begin_x=i,Begin_y=j;
else if(Map[i][j]=='3')End_x=i,End_y=j;
}
}
//cout<<Begin_x<<" "<<Begin_y<<endl<<End_x<<" "<<End_y<<endl;
dfs(Begin_x,Begin_y,0);
if(ans==0x7ffffff)cout<<-1<<endl;
else cout<<ans<<endl;
return 0;
}
这回没问题了吧......
然而只有80分
没有处理好特殊的‘4’
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int n,m;
int Begin_x,Begin_y,End_x,End_y;//存起始坐标与终止坐标
int ans=0x7ffffff;//答案
char Map[N][N];//存地图
bool t[N][N];//判断有没有走过
int dx[5]={0,1,-1,0,0},dy[5]={0,0,0,1,-1};//四个方向
int sm=6;//存生命
inline void dfs(int x,int y,int tot)
{
bool four=false;//判断这格是不是4
if(sm<=0||tot>=ans)return;//剪枝
if(x==End_x&&y==End_y)//更新答案
{
ans=min(ans,tot);
return;
}
for(int i=1;i<=4;i++)//四个方向搜索
{
int a=x+dx[i],b=y+dy[i];
if(a>0&&b>0&&a<=n&&b<=m&&Map[a][b]!='0'&&!t[a][b])
{
sm--;
t[x][y]=true;//设置为已走
int lssm=sm+1;//存一下当前生命+1(以便在回溯时候用)
if(Map[x][y]=='4')sm=6,four=true,Map[x][y]='1';//判断4的情况
dfs(a,b,tot+1);//搜索
sm++;
t[x][y]=false;
if(four)Map[x][y]='4',sm=lssm;
}
}
}
inline int read()//然而加不加都一样
{
int tot=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
tot=tot*10+c-'0';
c=getchar();
}
return tot*f;
}
int main()
{
n=read();
m=read();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>Map[i][j];
if(Map[i][j]=='2')Begin_x=i,Begin_y=j;
else if(Map[i][j]=='3')End_x=i,End_y=j;
}
}
dfs(Begin_x,Begin_y,0);//DFS
if(ans==0x7ffffff)cout<<-1<<endl;//特判
else cout<<ans<<endl;
return 0;
}