DFS 入门学习
A 全排列
#include <iostream>
using namespace std;
int n,a[15]={0};
bool vis[10]={0};
void dfs(int index){
if(index==n+1){
for(int i=1;i<index;i++){
if(i!=1) printf(" ");
printf("%d",a[i]);
}
printf("\n");
return ;
}
for(int i=1;i<=n;i++){
if(vis[i]==false){
a[index]=i;
vis[i]=true;
dfs(index+1);
vis[i]=false;
}
}
}
int main(){
while(cin>>n){
dfs(1);
}
return 0;
}
B 组合的输出
例如n = 5 ,r = 3 ,所有组合为:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
#include <iostream>
using namespace std;
int n,a[15]={0},p[20],k;
bool vis[10]={0};
void dfs(int index){
if(index==k+1){
for(int i=1;i<index;i++){
if(i!=1) printf(" ");
printf("%d",a[i]);
}
printf("\n");
return ;
}
for(int i=1;i<=n;i++){
if(vis[i]==false&&i>p[index-1]){
a[index]=i;
p[index]=i;
vis[i]=true;
dfs(index+1);
vis[i]=false;
}
}
}
int main(){
while(cin>>n>>k){
dfs(1);
}
return 0;
}
C 组合+判断素数
例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22 3+7+19=29 7+12+19=38 3+12+19=34。
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29。
#include <cstdio>
#include <iostream>
using namespace std;
int n,k, a[22],vis[22],p[22],sum=0,ans=0;
void dfs(int index);
bool IsPrime(int n);
int main(){
while(cin>>n>>k){
for(int i=1;i<=n;i++)
cin>>a[i];
dfs(1);
cout<<ans<<endl;
}
return 0;
}
void dfs(int index){
if(index==k+1){
if(IsPrime(sum))
ans++;
return ;
}
for(int i=1;i<=n;i++){
if(vis[i]==false&&i>p[index-1]){
p[index]=i;
sum+=a[i];
vis[i]=true;
dfs(index+1);
sum-=a[i];
vis[i]=false;
}
}
}
bool IsPrime(int n){
if(n<=1)
return false;
for(int i=2;i*i<=n;i++)
if(n%i==0)
return false;
return true;
D n皇后问题
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
int num=0, n, a[20];
void print(){
for(int i=1;i<=n-1;i++)
printf("%d ",a[i]);
printf("%d\n",a[n]);
}
bool IsDanger(int n){
for(int i=1;i<n;i++){
if(abs(a[n]-a[i])==(n-i)||a[n]==a[i])
return false;
}
return true;
}
void Queen(int index){
for(int i=1;i<=n;i++){
a[index]=i;
if(IsDanger(index)){
if(index==n){
print();
num++;
}
else
Queen(index+1);
}
}
}
int main(){
while(cin>>n){
Queen(1);
if(num==0)
cout<<"no solute!"<<endl;
}
return 0;
}
E 出栈序列统计
栈是常用的一种数据结构,有n令元素在栈顶端一侧等待进栈,栈顶端另一侧是出栈序列。你已经知道栈的操作有两•种:push和pop,前者是将一个元素进栈,后者是将栈顶元素弹出。现在要使用这两种操作,由一个操作序列可以得到一系列的输出序列。请你编程求出对于给定的n,计算并输出由操作数序列1,2,…,n,经过一系列操作可能得到的输出序列总数。
#include <iostream>
using namespace std;
int n, ans;
void dfs(int num, int push, int pop){
if(push==0&&pop==0){
ans++;
return ;
}
if(push>0)
dfs(num+1, push-1, pop);
if(pop>0&&num>0)
dfs(num-1, push, pop-1);
}
int main(){
while(cin>>n){
ans=0;
dfs(0, n, n);
cout<<ans<<endl;;
}
return 0;
F 走迷宫
输入
第一行是两个数n,m( 1 < n , m < 15 ),接下来是m行n列由1和0组成的数据,最后两行是起始点和结束点。
输出
所有可行的路径,描述一个点时用(x,y)的形式,除开始点外,其他的都要用“->”表示方向。如果没有一条可行的路则输出-1。
样例输入 [Copy](javascript:CopyToClipboard($(’#sampleinput’).text()))
5 6
1 0 0 1 0 1
1 1 1 1 1 1
0 0 1 1 1 0
1 1 1 1 1 0
1 1 1 0 1 1
1 1
5 6
样例输出 [Copy](javascript:CopyToClipboard($(’#sampleoutput’).text()))
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(3,4)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(3,4)->(4,4)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(3,4)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(3,4)->(3,5)->(4,5)->(5,5)->(5,6)
(1,1)->(2,1)->(2,2)->(2,3)->(3,3)->(4,3)->(4,4)->(4,5)->(5,5)->(5,6)
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n, index=0, flag=1, m, a[20][20], fx, fy, lx, ly;
int dx[4][2]={0,-1,-1,0,0,1,1,0};
struct book{
int x, y;
}g[500];
void dfs(int x, int y, int index){
g[index].x=x;
g[index].y=y;
if(x==lx&&y==ly){
flag=0;
printf("(%d,%d)",fx,fy);
for(int i=2;i<=index;i++)
printf("->(%d,%d)",g[i].x,g[i].y);
printf("\n");
return ;
}
for(int i=0;i<4;i++){
if(a[x+dx[i][0]][y+dx[i][1]]==1 && 1 <= x + dx[i][0] <= n && 1 <= y + dx[i][1] <= m){
a[x][y]=0;
dfs(x+dx[i][0],y+dx[i][1],index+1);
a[x][y]=1;
}
}
}
int main(){
while(cin>>n>>m){
flag=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
scanf("%d%d%d%d",&fx,&fy,&lx,&ly);
dfs(fx,fy,1);
if(flag)
cout<<-1<<endl;
}
return 0;
}
F题需要注意的地方是递归的地方是下一个地点,判断的是下一个地点,但是赋值为去过的是这一次的地点。剪枝可以减少时间。