一、深度优先搜索概念:
深度优先搜索是按照自己设置的方式在解空间中遍历搜索满足条件的解,如果将解空间视为一棵树,则深度优先搜索可以说是先序遍历解空间.当解空间过大时,我们可能不能在规定的时间内完成对答案的搜索,所以需要对不可能为答案的枝叶进行剪枝.
二、题目
1.小猫爬山(AcWing165)
思路:
我们先定义解空间是什么,这题解空间是将n只猫放入m个缆车中,状态转化是第i只猫该怎么放,我们可以将其放入已启用的其中一辆缆车,也可以放入一辆新的缆车中.当n只猫放完后的状态就是解空间的一个节点,由于复杂度过大,所以我们可以将不可能的枝叶剪除(即将以启用缆车数目大于目前最优解).又因为重量大的难放一些,所以可以猫先降序排列一下再进行搜索以减少搜索的解空间。
代码:
#include<bits/stdc++.h>
#define ll long long
#define eps 1e-8
using namespace std;
const ll inf=1e9+7;
const int N=2e5+5;
int a[N], vis[N], ans, k, n;
bool cmp(int x,int y)
{
return x>y;
}
void dfs(int v,int len)
{
if(v==n+1)
{
ans=min(ans,len);
}
else if(len<=ans)
{
for(int i=0; i<len; i++)
{
if(vis[i]+a[v]<=k)
{
vis[i]+=a[v];
dfs(v+1,len);
vis[i]-=a[v];
}
}
vis[len]=a[v];
dfs(v+1,len+1);
vis[len]=0;
}
}
int main()
{
scanf("%d%d",&n,&k);
ans=n;
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+1+n,cmp);
dfs(1,0);
printf("%d\n",ans);
return 0;
}
2.sudoku(Acwing166)
题意介绍:
有一个9*9的数独游戏,需要你对空的位置填数使其横竖以及小九宫格都有1-9.
思路:
dfs搜索填数,每次先填可填种类最少的位置,然后剪枝掉不可能的枝叶。
代码:
#include<bits/stdc++.h>
#define ll long long
#define eps 1e-8
using namespace std;
const ll inf=1e9+7;
const int N=2e5+5;
string s;
int d[15][15], a[105], ji, row[15], col[15], jiu[15], flag=0, jie[100005];
int fun(int v)
{
int x=v/10, y=v%10, val=0;
int z=((row[x]&col[y])&jiu[x/3*3+y/3]);
while(z)
{
z=z-(z&(-z));
val++;
}
return val;
}
void dfs(int k)
{
if(k==ji&&flag==0)
{
flag=1;
for(int i=0; i<9; i++)
{
for(int j=0; j<9; j++)
{
printf("%d",d[i][j]);
}
//printf("\n");
}
printf("\n");
return ;
}
else if(flag==0)
{
int mi=fun(a[k]), ki=k;
for(int i=k+1;i<ji;i++)
{
int pi=fun(a[i]);
if(mi>pi)
{
mi=pi;
ki=i;
}
}
swap(a[k],a[ki]);
int x=a[k]/10, y=a[k]%10;
int z=((row[x]&col[y])&jiu[x/3*3+y/3]);
while(z&&flag==0)
{
int ti=z&(-z);
int i=jie[ti];
row[x]^=(1<<i);
col[y]^=(1<<i);
jiu[x/3*3+y/3]^=(1<<i);
d[x][y]=i;
dfs(k+1);
d[x][y]=0;
row[x]^=(1<<i);
col[y]^=(1<<i);
jiu[x/3*3+y/3]^=(1<<i);
z=z-ti;
}
}
}
int main()
{
for(int i=1;i<=9;i++)
{
jie[1<<i]=i;
}
while(cin >> s)
{
if(s=="end")
{
break;
}
ji=0;
flag=0;
for(int i=0; i<9; i++)
{
row[i]=(1<<10)-2;
col[i]=(1<<10)-2;
jiu[i]=(1<<10)-2;
}
for(int i=0; i<9; i++)
{
for(int j=0; j<9; j++)
{
if(s[i*9+j]<='9'&&s[i*9+j]>='0')
d[i][j]=s[i*9+j]-48;
else
d[i][j]=0;
}
}
for(int i=0; i<9; i++)
{
for(int j=0; j<9; j++)
{
if(d[i][j]!=0)
{
if(((row[i]>>d[i][j])&1)==1)
{
row[i]-=(1<<d[i][j]);
}
if(((col[j]>>d[i][j])&1)==1)
{
col[j]-=(1<<d[i][j]);
}
if(((jiu[i/3*3+j/3]>>d[i][j])&1)==1)
{
jiu[i/3*3+j/3]-=(1<<d[i][j]);
}
}
else
{
a[ji++]=i*10+j;
}
}
}
dfs(0);
}
return 0;
}