前言:本系列(搜索)博客主要介绍的是用DFS解决一些问题,并不是图论中的DFS
dfs相信大家都有了解,TA是一个图论中的算法。
中心思想就是:只要干不死,就往死里干!
具体来说,就是只要符合要求,就一直往前搜,知道不行了再回头搜另一种。还是看题吧。
八皇后:
一道很经典的题目。思路就是每次枚举一个皇后,然后把这个皇后占领的所有格子标记,再枚举下一个就OK了。
#include <bits/stdc++.h>
using namespace std;
int row[100],col[100],l[100],r[100];
int ans;
void print(){if(ans<=2){for(int k=1;k<=n;k++)cout<<row[k]<<" ";cout<<endl;}ans++;
}
void dfs(int cnt){if(cnt>n){print();return;}else{for(int i=1;i<=n;i++){if((!col[i]) && (!l[cnt+i]) && (!r[cnt-i+n])){row[cnt]=i;col[i]=1;l[cnt+i]=1;r[cnt-i+n]=1;dfs(cnt+1);//回溯col[i]=0;l[cnt+i]=0;r[cnt-i+n]=0;}}}
}
int main(){int n; cin>>n;dfs(1);cout<<ans<<endl;return 0;
}
注意要回溯。
P2392:
为什么此题的作者不仅没被kkksc03封,还成了管理员?!?!?!?!?!?!?!?!?!?!?!?!?!
切入正题,那么由于kkksc03左右脑同时做2题(真牛),我们用一个l记录左脑,r记录右脑,枚举每道题交给哪边的脑子解决,找到两边时间较大值的最小值就结束了。
同时,虽然这题一打眼是贪心,但你会发现交上去全WA(或者几乎全WA)......
所以,老老实实DP或者DFS吧。
#include<bits/stdc++.h>
using namespace std;
int l,r,ans,tmp;
int s[4];
int t[21][4];
void dfs(int x,int sub){if(x>s[sub]){tmp=min(tmp,max(l,r));return;}l+=t[x][sub];dfs(x+1,sub);l-=t[x][sub];r+=t[x][sub];dfs(x+1,sub);r-=t[x][sub];
}
int main(){for(int i=0;i<4;i++)cin>>s[i];for(int i=0;i<4;i++){l=r=0;tmp=INT_MAX;for(int j=0;j<s[i];j++)cin>>t[j][i];dfs(0,i);ans+=tmp;}cout<<ans<<endl;return 0;
}
P2036:
思路很简单,dfs每次往后跑,如果超过n了就更新答案,要么添加,要么不添加,分别搜一下,就行了。而且,此题不需要回溯。
#include <bits/stdc++.h>
using namespace std;
int s[15],b[15];
int n,ans=INT_MAX;
void dfs(int idx,int sour,int bitter){if(idx>n){if(sour==1 && bitter==0)return;ans=min(abs(sour-bitter),ans);return;}dfs(idx+1,sour*s[idx],bitter+b[idx]);dfs(idx+1,sour,bitter);
}
int main(){cin>>n;for(int i=1;i<=n;i++)cin>>s[i]>>b[i];dfs(1,1,0);cout<<ans<<endl;return 0;
}
咦,为什么只有70?呵,满分就是70(我也不知道为什么)。
P1036:
突然发现了这个:数据范围说1小于等于n,所以当n=1,,k<n......
首先肯定要有一个判断素数的函数:
bool isprime(int n){for(int i=2;i<=n/i;i++){if(n%i==0)return false;}return true;
}
然后就是剩下的数挨个枚举选不选就行了。
void dfs(int idx,int sum,int lst){if(idx==k && isprime(sum)){ans++;return;}for(int i=lst;i<n;i++)dfs(idx+1,sum+x[i],i+1);
}
所以下面是完整代码:
#include <bits/stdc++.h>
using namespace std;
int x[10];
int n,k,ans;
bool isprime(int n){for(int i=2;i<=n/i;i++){if(n%i==0)return false;}return true;
}
void dfs(int cnt,int sum,int lst){if(cnt==k && isprime(sum)){ans++;return;}for(int i=lst;i<n;i++)dfs(cnt+1,sum+x[i],i+1);
}
int main(){cin>>n>>k;for(int i=0;i<n;i++)cin>>x[i];dfs(0,0,0);cout<<ans<<endl;return 0;
}
OK,以上就是本期的全部内容了。下期我会聊一聊记忆化和剪枝。ヾ( ̄▽ ̄)Bye~Bye~
温馨提示:本期的全部代码直接提交就无法AC,请不要无脑Ctrl C+Ctrl V