按照老师的要求,看了看洛谷上一些关于搜索的题目,不过能看懂的只有一些普及-的题。
做了做前十一道题目,但是事实上除去一些简单的搜索,能自己码出来代码不看题解的只有一类问题,染色问题。
分别是
[USACO10OCT]Lake Counting S - 洛谷
先讲讲我对这类问题的理解。这种题目的特点是,给出一片区域,对区域中的特殊区域或特殊点进行计数统计。这种问题的解题思路非常简单,对着这片区域进行搜索,遇到符合的特殊点,标记并对其深搜,使得其附近所有特殊点均被上上标记,以此根据问题的需要给出特殊点的数目或特殊区域的数目。
比如拯救oibh总部这道题
#include <iostream>
using namespace std;
char s[500][500];
int p,q;
void dfs(int a,int b)
{
if(a>p+1||a<0||b>q+1||b<0||s[a][b]=='*')
return;
else
{
s[a][b]='*';
dfs(a-1,b);
dfs(a+1,b);
dfs(a,b+1);
dfs(a,b-1);
}
}
int main()
{
cin>>p>>q;
for(int i=1; i<=p; i++)
for(int j=1; j<=q; j++)
cin>>s[i][j];
dfs(0,0);
int num=0;
for(int i=1; i<=p; i++)
for(int j=1; j<=q; j++)
if(s[i][j]=='0')
num++;
cout<<num;
}
染色题应该是搜索中较简单的题目,类型单一思路简单。
然后是一些简单递归的题目
[USACO2.1]健康的荷斯坦奶牛 Healthy Holsteins - 洛谷
这类问题的特点是,将所有的可能计算出来,通过筛选选择出符合题意的题解。
解题思路,一种非常朴实无华的深搜,每搜完一个枝条记录一次,选出符合题意的解。
比如选数问题
#include <iostream>
using namespace std;
bool bj(int n)
{
for(int i=2; i<n; i++)
if(n%i==0)
return 0;
return 1;
}
int s[22]= {0};
int n,k,ans=0;
int dfs(int i,int nums,int sum)
{
if(nums==k)
{
if(bj(sum))
{
ans++;
}
}
else if(i<=n)
{
dfs(i+1,nums,sum);
dfs(i+1,nums+1,sum+s[i]);
}
}
int main()
{
cin>>n>>k;
for(int i=1; i<=n; i++)
{
cin>>s[i];
}
dfs(1,0,0);
cout<<ans;
return 0;
}
这类问题不花哨,不拐弯,比较简单。
剩下的四道题,能明白题意,想不出来怎么去做,码不出代码,只能通过看题解去了解解题思路。
在一些博客中,我去更加深入的了解了剪枝的主要用法及好处,通过剪枝,可以使得程序的运行更加高效,迅速,有效避免超时问题。
和深搜有关的几种题型
简单递归,树的搜索,暴力枚举,图的搜索,排列组合
在老师发的题单中这些问题都涉及到了,但是实际上我码起代码都不是很熟练甚至可以说是非常困难,题目思路出的慢,代码出的更慢,导致做题效率不高,简单题不想做,难题磕不出,有时候浪费几个小时都出不来一道题。
虽然学习了很长一段时间的搜索,但是感觉还是只学到了皮毛,可能还是做题少的原因,周六的比赛也是一道题都没有做出来,感觉思路打不开,方法想不到。
深搜主要思想递归,实际上理解的并不是非常通透,感觉现在做深搜题目靠的就是套路,判断题目类型套上递归,至于这种递归方式应该如何被想到,还能有什么递归方式,统统不知道。
想要代码码的又好又快,思路清晰明了,还得是看书刷题看书刷题和看书刷题啊,编程之路,任重而道远。