1.八皇后问题
dfs一般框架
int dfs(int k){
if(到达目的地){
输出结果
}else{
for(int i=1;i<=每一步算法数量;i++){
if(满足条件){
保存结果;
递归dfs(k+1);
回溯前一步,一般与保存结果那一步相反。
}
}
}
}
八皇后问题代码
#include<iostream>
using namespace std;
int a[10] = {0};
int g[10][10] = {0};
int count = 0;
bool test(int i,int j){
for(int k=1;k<=i-1;k++){
if(a[k] == j||a[k] == i+j-k||a[k] == k-i+j){
return false;
}
}
return true;
}
void pp(int n){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
printf("%d ",g[i][j]);
}
printf("\n");
}
printf("\n");
}
void clear(int n){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
g[i][j] = 0;
}
}
}
void dfs(int k,int n){ //准备放置第k个皇后
if(k == n+1){ //终结条件
pp(n);
count++;
}else{
for(int i=1;i<=n;i++){
if(test(k,i) == true){ //可放置
a[k] = i;
g[k][i] = 1;
dfs(k+1,n);
//复原
a[k] = 0;
g[k][i] = 0;
}
}
}
}
int main()
{
int n; //n*n的棋盘上,n皇后
cin>>n;
dfs(1,n);
cout<<count<<endl;
return 0;
}
2.一道dfs习题试做
n个结点,编号1到n,并输入m条边,边的形式为u、v、t1、t2,表示u和v间存在一条边,该边的初始权重为t1,表示u到v需要t1秒,过了一秒后权重为t2,表示此时u到v需要t2秒,再过一秒又变回t1…以此类推。在某一个结点上,可以等,也可以走。问从1到达n最少需要多少时间。
#include<iostream>
#include<vector>
#include <cstring>
#include<limits>
using namespace std;
#define MAXN 20000
#define INF INT_MAX
struct Edge{
int to;
int weight;
Edge(int t,int w):to(t),weight(w){};
}; //边
vector<Edge> graph1[MAXN]; //邻接表法
vector<Edge> graph2[MAXN];
bool hasTraverse[MAXN];
int min_time = INF;
int exp_time = 0;
int current_node = 0;
void Init(){
for(int i=0;i<MAXN;i++){
hasTraverse[i] = false;
}
}
void dfs(int n){ //n个结点深度优先搜索
if(current_node == n-1){
if(min_time>exp_time){
min_time = exp_time;
}
return;
}else if(graph1[current_node].size() == 0){
return;
}else{
for(int i=0;i<graph1[current_node].size()*2;i++){
//*2是因为可以等待
int add_time;
int record_pre_node = current_node;
if(i<graph1[current_node].size()){
//不等待
if(exp_time % 2 == 0 && hasTraverse[graph1[current_node][i].to] == false){
add_time = graph1[current_node][i].weight;
current_node = graph1[current_node][i].to;
hasTraverse[current_node] = true;
}else if(exp_time %2 == 1 && hasTraverse[graph2[current_node][i].to] == false){
add_time = graph2[current_node][i].weight;
current_node = graph2[current_node][i].to;
hasTraverse[current_node] = true;
}
}else{
//等待
if(exp_time % 2 == 0 && hasTraverse[graph2[current_node][i-graph2[current_node].size()].to] == false){
add_time = 1+graph2[current_node][i-graph2[current_node].size()].weight;
current_node = graph2[current_node][i-graph2[current_node].size()].to;
hasTraverse[current_node] = true;
}else if(exp_time %2 == 1 && hasTraverse[graph1[current_node][i-graph1[current_node].size()].to] == false){
add_time = 1+graph1[current_node][i-graph1[current_node].size()].weight;
current_node = graph1[current_node][i-graph1[current_node].size()].to;
hasTraverse[current_node] = true;
}
}
exp_time += add_time;
dfs(n);
exp_time -= add_time;
if(i<graph1[current_node].size()){
hasTraverse[current_node] = false;
}else{
hasTraverse[current_node] = false;
}
current_node = record_pre_node;
}
}
}
int main()
{
int n;
cin>>n;
int m; //m条边
cin>>m;
memset(graph1,0,sizeof(graph1)); //初始化
memset(graph2,0,sizeof(graph2));
int u,v,t1,t2;
for(int i=0;i<m;i++){
cin>>u>>v>>t1>>t2;
graph1[u-1].push_back(Edge(v-1,t1));
graph2[u-1].push_back(Edge(v-1,t2));
}
Init(); //初始化
hasTraverse[0] = true;
dfs(n);
cout<<min_time<<endl;
return 0;
}
思路:邻接表法表示图,dfs搜索状态空间。
在当前状态下 ,有两大类分支,第一大类:采用当前各边权重立即走,第二大类:等1s后采用1s后各边的权重走。展开dfs树,回溯。
for循环种i<graph1[current_node].size()2,这里的2正是因为有两大类分支。