饭可以不吃,水可以不喝,题不能不做!!
最近写dfs有点上瘾,就多发一些,反正这个栏目都是洛谷的题解,我写到哪就发到哪力,要是有洛谷什么的题不会可以发评论或私信,emm,应该会看,只要我会的话肯定发题解,不会的话,争取用最少的手段搞会......额,下面看AC代码吧!!
#include<iostream>
using namespace std;
const int N=110;
string s[N];
int n,m,k;
int ans=0;
int dx[]={0,1};
int dy[]={1,0};
void dfs(int x,int y,int sum,int step){
if(sum>=k){
if(sum==k){
ans++;
}
return ;
}
int a=x+dx[step],b=y+dy[step];
if(a<0||b<0||a>=n||b>=m) return ;
if(s[a][b]!='.') return ;
dfs(a,b,sum+1,step);
return ;
}
int main(){
cin>>n>>m>>k;
for(int i=0;i<n;i++){
cin>>s[i];
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(s[i][j]=='.'){
//dfs(i,j,0);
for(int q=0;q<2;q++){
dfs(i,j,1,q);
}
}
}
}
if(k==1){
ans/=2;
}
cout<<ans<<endl;
return 0;
}
好,那么好,下面就是激动人心的讲解(剖析)代码の时刻了:
dfs模板做得多的同学,其实大部分是可以看懂的,dfs题目真正难的是细节,是脱离于模板、输入输出之外的,对题意的理解,是什么时候去搜索,怎么样进行搜素,想更进一步还要考虑正确的剪枝......这些问题都建立于大量的积累之上。。好像今天废话较多。。
好了好了,先从main函数开始看吧,对数据的输入就不多说了,只有一点要注意,你的地图也就是此代码中的字符串s的下标是从0还是1开始输入的,这关系到你从哪里开始搜,边界条件要怎么写。下面是两重for循环加个if判断,目的是从可以放人的地方开始,其中又有一个q为变量的循环,他的意思是让排列只从横向或者只从纵向开始找,体现在代码上就是一次dfs的参数step即q不是0就是1(满足题意)。
接着看dfs函数推荐从比较靠下的部分开始看,因为是怎么找的思路的体现,那就先从定义a,b开始,如果在这里写个i从0到1的for循环,就代表着这个队可以随时拐弯,因此不满足题意,所以就有了main函数中的q的那个for循环,定义完a,b后就是判断边界以及能不能放人的条件判断,都满足就继续找下一个,直到sum==k回溯,还有还有sum的初始值一定要初始化为1,因为如果可以搜素的话就代表已经找到了一个可以放人的地方。dfs差不多就说完了。
最后,看下k==1的特判,因为k=1的话意味着向下和向右会重复计算,所以需要除以2。(要是不加这个测试点4、5会WA)。
又是充实的一天,哈哈,其实才认真写了一道题,一篇题解而已,不过,也不错,没有什么都不做,起码有所收获,虽然小而已,让下面史铁生《我与地坛》中的一句话为结尾吧(
但是太阳,它每时每刻都是夕阳也都是旭日。当它熄灭着走下山去收尽苍凉残照之际,正是它在另一面燃烧着爬上山巅布散烈烈朝辉之时。那一天,我也将沉静着走下山去,扶着我的拐杖。有一天,在某一处山洼里,势必会跑上来一个欢蹦的孩子,抱着他的玩具。
当然,那不是我。
但是,那不是我吗?
宇宙以其不息的欲望将一个歌舞炼为永恒。这欲望有怎样一个人间的姓名,大可忽略不计。