第二天,打卡;
目录
D.Tempter of the Bone HDU 1010
前言
dfs的基本概念和模板不在详细介绍,可以自行查阅博客学习
讲解详见 (21条消息) DFS(深度优先搜索算法)_无限迭代中......-CSDN博客_dfs深度优先搜索
模板详见(21条消息) BFS/DFS 模板 代码_Lemon_Chen-CSDN博客_bfs dfs 代码
dfs基本上是模板题,但其中的小细节值得注意
A.Oil Deposits POJ-1562
模板题
AC代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=105;
int m,n;
char ch[N][N];
int vis[N][N];
int vst[N][N];
bool check(int p,int q)
{
if(p<0 || p>=n || q<0 || q>=m)
return false;
if(vst[p][q]==0)
return true;
return false;
}
void dfs(int x,int y)
{
vst[x][y]=1;
for(int dx=-1;dx<=1;dx++)
{
for(int dy=-1;dy<=1;dy++)
{
int nx=x+dx,ny=y+dy;
if(check(nx,ny))
{
dfs(nx,ny);
}
}
}
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF){
getchar();
int ans=0;
if(n==0&&m==0) break;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>ch[i][j];
if(ch[i][j]=='@')
vst[i][j]=0;
else
vst[i][j]=1;
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(!vst[i][j])
{
dfs(i,j);
ans++;
}
}
}
printf("%d\n",ans);
}
return 0;
}
B.全排列 51Nod 2060
最基础的一道dfs题
AC代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=10;
int a[N];
int vis[10];
int n;
void print()
{
for(int i=1;i<=n;i++)
cout << a[i] << " ";
cout << endl;
}
void dfs(int x)
{
if(x>n)
{
print();
return;
}
for(int i=1;i<=n;++i)
{
if(!vis[i])
{
vis[i]=1;
a[x]=i;
dfs(x+1);
vis[i]=0;
}
}
return;
}
int main()
{
cin >> n;
dfs(1);
return 0;
}
C.泉水 HRBUST 1143
需要注意水只能流向低处,所以流向的地方必须低于泉眼才能继续递归下去
AC代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int N=1005;
bool vis[N][N];
int high[N][N];
int dir[4][2]={0,1,0,-1,1,0,-1,0};
int p1,p2,m,n;
int ans;
bool check(int x,int y)
{
if(x>0&&x<=n&&y>0&&y<=m&&!vis[x][y]&&high[x][y]<=high[p1][p2])
return true;
else
return false;
}
void dfs(int x,int y)
{
ans++;
vis[x][y]=1;
for(int i=0;i<4;i++)
{
int nx=x+dir[i][0];
int ny=y+dir[i][1];
if(check(nx,ny))
dfs(nx,ny);
}
}
int main()
{
while(scanf("%d %d %d %d",&n,&m,&p1,&p2)!=EOF)
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin >> high[i][j];
ans=0;
dfs(p1,p2);
cout << ans << endl;
}
return 0;
}
D.Tempter of the Bone HDU 1010
这题格外要注意剪枝的问题,如果不使用奇偶剪枝,就会超时。
dis=abs(x-p)+abs(y-q),从起点到终点的步数是确定的,所以可以剪枝
AC代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=10;
char ch[N][N];
int vis[N][N];
int vst[N][N];
int dir[4][2]={0,1,0,-1,1,0,-1,0};
int t,n,m;
int flag=0;
int x,y,p,q;
void dfs(int x,int y,int cnt)
{
if(flag==1)
return;
if(cnt==t&&x==p&&y==q)
{
flag=1;
return;
}
for(int i=0;i<4;i++)
{
int nx=x+dir[i][0];
int ny=y+dir[i][1];
if(x>=0 && y>=0 && x<n && y<m && !vis[nx][ny] && cnt<=t &&!vst[nx][ny])
{
vis[nx][ny]=1;
dfs(nx,ny,cnt+1);
vis[nx][ny]=0;
}
}
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&t))
{
if(n==0)
break;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
cin >> ch[i][j];
if(ch[i][j]=='S')
{
x=i,y=j;
}
else if(ch[i][j]=='D')
{
p=i,q=j;
}
else if(ch[i][j]=='X')
vst[i][j]=1;
else
vst[i][j]=0;
}
int dis=abs(x-p)+abs(y-q);//奇偶剪枝
if((dis%2)!=(t%2))
{
printf("NO\n");
continue;
}
memset(vis,0,sizeof(vis));
flag=0;
vis[x][y]=1;
dfs(x,y,0);
if(flag==1)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}
E.Prime Ring Problem HDU 1016
常规题
AC代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N =25;
int vis[N],a[N],is_prime[N];
int n;
int prim(int n)
{
if(n==1)
return 0;
for(int i=2;i<n;++i)
if(n%i==0)
return 0;
return 1;
}
void dfs(int v)
{
if(v==n)
{
if(!is_prime[a[v]+a[1]])
return;
for(int i=1;i<n;++i)
printf("%d ",a[i]);
printf("%d\n",a[n]);
}
for(int i=2;i<=n;++i)
{
if(!vis[i]&&is_prime[a[v]+i])
{
a[v+1]=i;
vis[i]=1;
dfs(v+1);
vis[i]=0;
}
}
}
int main()
{
int cnt=1;
for(int i=1;i<=50;++i)
is_prime[i]=prim(i);
while(~scanf("%d",&n))
{
memset(vis,0,sizeof(vis));
printf("Case %d:\n",cnt++);
a[1]=1;
dfs(1);
printf("\n");
}
return 0;
}
F.马走日 OpenJ_Bailian - 4123
模板题
AC代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=20;
int vis[N][N];
int dir[8][2] = {{1,2},{-1,2},{1,-2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}};
int ans=0,nm;
int n,m,x,y;
void dfs(int x,int y,int cnt)
{
if(cnt==nm)
{
ans++;
return;
}
else
{
for(int i=0;i<8;++i)
{
int nx=x+dir[i][0];
int ny=y+dir[i][1];
if(nx >= 0 && ny >= 0 && nx < n && ny < m && !vis[nx][ny])
{
vis[nx][ny]=1;
dfs(nx,ny,cnt+1);
vis[nx][ny]=0;
}
}
}
}
int main()
{
int t;
cin >> t;
while(t--)
{
memset(vis,0,sizeof(vis));
cin >> n >> m >> x >> y;
ans=0;
nm=n*m;
vis[x][y]=1;
dfs(x,y,1);
cout << ans << endl;
}
return 0;
}
G.ROADS POJ - 1724
这道题需要用图来存储数据,这里选用的是链式前向星的方式,让后再按照dfs的做法来做
具体链式前向星的讲解详见(21条消息) 链式前向星--最通俗易懂的讲解_sugarbliss-CSDN博客_链式前向星
AC代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=10000+5;
int h[N],ne[N],vis[N];
int minn,flag;
int k,n,r;
struct Edge
{
int to,l,w;
} edge[10101];
void add_edge(int u, int v, int w,int l,int i)
{
edge[i].to = v;
edge[i].w = w;
edge[i].l = l;
ne[i]=h[u];
h[u]=i;
}
void dfs(int x,int num,int sum)
{
if(num>k)
return;
if(sum>minn)
return ;
if(x==n&&num<=k)
{
if(sum<minn)
{
flag=1;
minn=sum;
}
return ;
}
for(int i=h[x];i!=-1;i=ne[i])
{
if(vis[edge[i].to]==0)
{
vis[edge[i].to]=1;
dfs(edge[i].to,num+edge[i].w,sum+edge[i].l);
vis[edge[i].to]=0;
}
}
}
int main()
{
int s,d,l,t;
while(~scanf("%d%d%d",&k,&n,&r))
{
memset(h,-1,sizeof(h));
memset(ne,-1,sizeof(ne));
memset(vis,0,sizeof(vis));
for(int i=0;i<r;i++)
{
scanf("%d%d%d%d",&s,&d,&l,&t);
add_edge(s,d,t,l,i);
}
vis[1]=1;
minn=0x3f3f3f3f;
flag=0;
dfs(1,0,0);
if(flag==0)
printf("-1\n");
else
printf("%d\n",minn);
}
return 0;
}
H.N皇后问题 HDU 2553
此题需要将数据储存起来打表,不然会超时
AC代码
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int a[50],b[50],c[50],d[50];
int ans = 0;
bool check(int x,int y)
{
if(!a[x]&&!b[y]&&!c[x+y]&&!d[x-y])
return true;
else
return false;
}
void bfs(int n,int x)
{
if(x>n-1)
{
ans++;
return;
}
for(int i=0;i<n;i++)
{
if(check(x+1,i))
{
a[x+1]=1,b[i]=1,c[x+i+1]=1,d[x-i+1]=1;
bfs(n,x+1);
a[x+1]=0,b[i]=0,c[x+i+1]=0,d[x-i+1]=0;
}
}
}
int main()
{
int sum[15];
int n;
for(int i=1;i<=10;i++)
{
memset(a,0,sizeof(a));
ans=0;
bfs(i,0);
sum[i]=ans;
}
while(cin >> n)
{
if(n==0)
return 0;
cout << sum[n] << endl;
}
return 0;
}
总结
dfs需要熟记模板,需要注意初始化的问题,和记录走过的问题,细枝末节是WA发生的原因。
另外剪枝的问题也需要注意。