Kuangbin搜索总结
A - 棋盘问题 POJ - 1321
这道题没有用到剪枝,就是要考虑状态,题目要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,那么我们可以在dfs(int cur)cur代表当前行,所以直接只用考虑列,行数在增加列数做好标记。注意cnt,ans的区别。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=10;
char map[maxn][maxn];
int col[maxn];
int n,k,ans,cnt;
void dfs(int cur)//cur代表当前行
{
if(cnt==k)
{
ans++;
// cout<<ans<<endl;
return;
}
if(cur>=n)//递归出口
{
return;
}
for(int i=0;i<n;i++)
{
if(!col[i]&&map[cur][i]=='#')
{
col[i]=1;
cnt++;
dfs(cur+1);
col[i]=0;
cnt--;
}
}
dfs(cur+1);
}
int main()
{
while(cin>>n>>k)
{
memset(col,0,sizeof(col));
if(n==-1||k==-1)
break;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>map[i][j];
}
}
cnt=0;ans=0;
dfs(0);
printf("%d\n",ans);
}
return 0;
}
E - Find The Multiple POJ - 1426
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int n,flag;
void dfs(int cur,ll num)
{
if(cur==19||flag)
{
return;
}
if(num%n==0)
{
// flag=1;
cout<<num<<endl;
flag=1;
return;
}
dfs(cur+1,num*10);
// cout<<num<<"\t"<<cur<<endl;
dfs(cur+1,num*10+1);
}
int main()
{
while(cin>>n&&n)
{
flag=0;
//dfs(1,0);
dfs(0,1);
}
return 0;
}
注意一些优化,可以用记忆化搜索进行优化,还有递归出口和递归的限制条件,一般情况下是把递归的出口放在递归的限制性条件后面,这样可以优化很多。
L - Oil Deposits HDU - 1241
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=101;
int nex[8][2]={{1,0},{-1,0},{0,1},{0,-1},
{1,-1},{1,1},{-1,-1},{-1,1}};
char map[maxn][maxn];
// int vis[maxn][maxn];
int n,m,ans;
void dfs(int row,int col)
{
int nowx,nowy;
// if(row>=m||col>=n||row<0||col<0)
// return;
map[row][col]='*';
for(int k=0;k<8;k++)
{
nowx=row+nex[k][0];
nowy=col+nex[k][1];
if(map[nowx][nowy]=='@')
{
dfs(nowx,nowy);
}
// if((map[row][col]=='@')&&(map[nowx][nowy]=='@')&&(vis[nowx][nowy]!=0))
// {
// ans++;
// }
}
}
int main()
{
while(cin>>n>>m&&m!=0)
{
// memset(vis,0,sizeof(vis));
ans=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>map[i][j];
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(map[i][j]=='@')
{
dfs(i,j);
ans++;
}
}
}
cout<<ans<<endl;
}
return 0;
}
这几道题貌似都没有标记数组进行标记,但是都过了,这是因为做了相关优化和剪枝,最后一道题注意不用dfs里面限制条件,因为开始的时候初始化所有的连通块都初始化为"*"这才是正确解法,为什么要全部初始化为"*",因为访问过的都由@变成*这是剪枝的一个操作。省略了标记的作用,随后补其他题,这些都是深搜入门题。