您的位置:首页 > 其它

ACM_程序设计竞赛:穷举法:DFS(深度优先)

2016-03-30 01:11 465 查看

DFS的伪码

从顶点v出发;

访问v相邻且未被访问的顶点w1w_1

依次w2,....,w_2,....,,直到不能继续

退回到出发点v,

若v的领域还有为访问结点,重复上述

//结果:abdceghf



bool visited[MAX_VERTEX_NUM]; //访问数组标记
void DFSTraverse(Graph G)
{
//对图G深度遍历,访问函数是visit()
for(v=0; v<G.vexnum;++v)
visited[v]=FALSE; // 初始化访问标记
for(v=0;v<G,vexnum;++v) //从v=0开始遍历
if(!visited[v])
DFS(G,v);
}

void DFS(Graph G, int v)
{ //从顶点v出发,采用递归,深度遍历
visit(v); // 访问顶点v
visited[v]=TRUE; //标记访问
for(w=FirstNeighbor(G,v); w>=0;w=NextNeighor(G,v,w))
//FirstNeighbor()=图G中顶点x的第一个领接点,有则返回序列号
//NextNeighor()=如果y是x的一个领接点,返回除y之外的顶点x的下一个领接点号
if(!visited[w])
DFS(G,w);
}


复杂度

借助栈工作:空间复杂度:O(|V|)

领接矩阵:查找每个顶点的时间复杂度是O(|v|2)O(|v|^2)

领接表:查找的时间(O(|E|)),访问的时间O(|v|); 总时间=O(|V|+|E|)

部分和问题

给定整数:a1,a2,...,ana_1,a_2,...,a_n, 判断是否可以从中选出若干数,是其和恰好是k

*限制条件

1<=n<=201 <= n <=20

−108<=ai<=108-10^8 <=a_i <=10^8

−108<=k<=108-10 ^8 <=k <= 10^8

例子

输入:

n=4

a={1,2,4,7}

k=13

输出:

YES {13=2+4+7}

例子

输入:

n=4

a={1,2,4,7}

k=15

输出:

NO

伪代码

//  输入:
int a[MAX_N];
int n;  //数组个数
int k; //部分和

//前i项得到了和sum,现在对i项之后分支计算
dfs(项数i,部分和sum)
1.0 如果,i==n ; 判断是否sum==k;
2.0 不加a[i];
2.1 如果,dfs(i+1,sum)成立,返回,true;
3.0 加上a[i]
3.1 如果dfs(i+1,sum+a[i])成立,返回,true
4.0 都不成立返回,false

solve()

1.0  if(dfs(0,0)), true,打印
2.0  if(dfs(0,0)),false,打印


#include <iostream>
using namespace std;

bool dfs (int i, int sum, int* a, int n, int k) {
if (i==n) return sum == k;
if(dfs(i+1, sum, a, n, k)) return true;
if(dfs(i+1, sum+a[i], a, n, k)) return true;
return false;
}

void solve(int* a, int n, int k) {
if (dfs(0,0,a,n,k))
cout<<"Yes"<<'\n';
else
cout <<"No"<<'\n';
);
}

int main(void)
{
const int MAX_N = 20;
int a[MAX_N] = {1, 2, 4, 7};
int n = 4, k = 13; //k位需要找到的数字

solve(a, n, k);

return 0;
}


赋值度

O(2n)O(2^n)

lake counting

题目

大小为 N*M 的园子,雨后积水,八连通的积水被认为是联系在一起的,求园子有多少水洼

//八连通
***
*w*
***
//输入:N=10,M=12;
(w表示积水,*表示没有水)

w*********ww*
*www******www
****ww***ww*
*********ww*
*********w**
**w******w**
*w*w*****ww*
w*w*w*****w*
*w*w******w*
**w*******w*

//输出:3


算法:

从任意w开始,将领接部分用”*”替换

1次DFS后,与初始ww连接的所有w都被替换为∗*

知道图中没有w

总共进行的DFS次数就是水洼数

复杂度:O(8*N*M)

#include <iostream>
using namespace std;

const int MAX_N = 10;
const int MAX_M = 12;

char field[MAX_N][MAX_M+1] = {
"+********++*",
"*+++*****+++",
"****++***++*",
"*********++*",
"*********+**",
"**+******+**",
"*+*+*****++*",
"+*+*+*****+*",
"*+*+******+*",
"**+*******+*"
};

//现在位置(x,y)
void dfs(int x, int y){
field[x][y]='.';

//循环遍历移动的8个方向
for(int dx=-1;dx<=1;dx++){
for(int dy=-1;dy<=1;dy++){
//x方向移动dx,y方向移动dy,移动结果(nx,ny)
int nx=x+dx,ny=y+dy;
//判断(nx,ny)是不是园子内及是否有积水
if(0<=nx && nx<MAX_N && 0<=ny && ny<MAX_M && field[nx][ny]=='+')
dfs(nx,ny);
}
}
return ;
}

void solve(){
int res=0;
for(int i=0;i<MAX_N;i++){
for(int j=0;j<MAX_M;j++){
if(field[i][j]=='+'){
dfs(i,j);
res++;
}
}
}
cout<<res<<'\n'<<endl;
}

int main(int argc, char* argv[])
{
solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: