深度优先搜索(二)寻路问题poj1724

寻路问题:

 思路:

从城市1开始深度优先遍历整个图,找到所有能到达N的走发,选出一个最优的。

于是得到如下代码(该代码由于超时不能ac):

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int K, N, R;
struct Road {
	int d, L, t;//路的终点、长度、过路费
};
vector<vector<Road>>G(110);//相当于一个二维数组
//G[i] 这个节点表示从i这个点延出去的边

int minLen;//最佳路径长度
int totalLen;//正在探索的路已经走了多长
int totalCost;//长在探索的这条路已经花了多少钱
int visited[110];//标志数组,用来表示城市有没有走过
void dfs(int s) {//从s点出发进行深度优先搜索
	if (s == N) {
		minLen = min(minLen, totalLen);
		return;
	}
	for (int i = 0; i < G[s].size(); ++i) {
		Road r = G[s][i];
		if (totalCost + r.t > K)
			continue;//钱不够回到循环,试下一条边
		if (!visited[r.d]) {//判断是否走过
			totalLen += r.L;
			totalCost += r.t;
			visited[r.d] = 1;
			dfs(r.d);
			visited[r.d] = 0;//撤销之前标记,防止影响别的走法
			totalLen -= r.L;
			totalCost -= r.t;
		}
	}
}
int main() {
	cin >> K >> N >> R;
	for (int i = 0; i < R; i++) {//读入数据
		int s;
		Road r;
		cin >> s >> r.d >> r. L >> r.t;
		if (s != r.d) {
			G[s].push_back(r);
		}
	}
	memset(visited, 0, sizeof(visited));//初始化为零
	totalLen = 0;
	minLen = 1 << 30;
	totalCost = 0;
	visited[1] = 1;
	dfs(1);
	if (minLen < (1 << 30)) {
		cout << minLen << endl;
	}
	else
		cout << "-1" << endl;
	return 0;
}

但上传到oj平台上却因为超时而不能ac,于是便需要用到最优性剪枝,也就是多加几个判断条件来减少程序的运算量从而来减少所需时间。

本题多加的判断条件有:

(1)将当前的走过的总长度和之前找到的最优路径长度进行比较,如果当前的长度大于之前的最优路径长度就直接放弃该走法,不用走到低。

(2)自定义一个二维数组,用于存放中间计算结果的最优路径,也就是比较到达同一位置、所花相同的钱,所走的路程长度。

具体代码如下(此代码能ac):

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int K, N, R;
struct Road {
	int d, L, t;//路的终点、长度、过路费
};
vector<vector<Road>>G(110);//相当于一个二维数组
//G[i] 这个节点表示从i这个点延出去的边

int minL[110][10010];//记入城市和和钱的数目
//minL[i][j]从起点1到城市i花了j块钱

int minLen;//最佳路径长度
int totalLen;//正在探索的路已经走了多长
int totalCost;//长在探索的这条路已经花了多少钱
int visited[110];//标志数组,用来表示城市有没有走过
void dfs(int s) {//从s点出发进行深度优先搜索
	if (s == N) {
		minLen = min(minLen, totalLen);
		return;
	}
	for (int i = 0; i < G[s].size(); ++i) {
		Road r = G[s][i];
		if (totalCost + r.t > K)
			continue;//钱不够回到循环,试下一条边
		if (!visited[r.d]) {//判断是否走过
			if (totalLen + r.L >= minLen)//判断走到r.d的长度是否已经超过了之前不同走法的出来的minLen
				continue;
			if (totalLen + r.L >= minL[r.d][totalCost + r.t])//最优性剪枝,比较到达同一位置、所花相同的钱,所走的路程长度
				continue;
			minL[r.d][totalCost + r.t] = totalLen + r.L;//更新数据
			totalLen += r.L;
			totalCost += r.t;
			visited[r.d] = 1;
			dfs(r.d);
			visited[r.d] = 0;//撤销之前标记,防止影响别的走法
			totalLen -= r.L;
			totalCost -= r.t;
		}
	}
}
int main() {
	cin >> K >> N >> R;
	for (int i = 0; i < R; i++) {//读入数据
		int s;
		Road r;
		cin >> s >> r.d >> r.L >> r.t;
		if (s != r.d) {
			G[s].push_back(r);
		}
	}
	memset(visited, 0, sizeof(visited));//初始化为零
	totalLen = 0;
	minLen = 1 << 30;
	totalCost = 0;
	visited[1] = 1;
	for (int i = 0; i < 110; ++i)
		for (int j = 0; j < 10010; ++j)
			minL[i][j] = 1 << 30;//初始化置成一个大数
	dfs(1);
	if (minLen < (1 << 30)) {
		cout << minLen << endl;
	}
	else
		cout << "-1" << endl;
	return 0;
}

 大数据201 liyang

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值