程序设计与算法(二)算法基础9.1寻路问题(剪枝思想)

N个城市,编号1到N。城市间有R条单向道路。每条道路连接两个城市,有长度和过路费两个属性。Bob只有K块钱,他想从城市1走到城市N。问最短共需要走多长的路。如果到不了N
输出-1
输入:
2<=N<=100
0<=K<= 10000
1<=R<=10000
每条路的长度L, 1 <= L<= 100
每条路的过路费T, 0 <= T <= 100
输入格式:

共R+3行:前三行分别为K,N,R;后R行每一行以此为路的起始城市,目的地,长度和过路费;

样例1:

样例输入
5
6
7
1 2 2 3
2 4 3 3
3 4 2 4
1 3 4 1
4 6 2 1
3 5 2 0
5 4 3 2
样例输出
11

#include<bits/stdc++.h>
using namespace std;
int k,n,t;
struct road{
	int end,len,money;
};
vector<vector<road>>g;//存放各个城市,其数据road的意义是从g[i]出发的各个道路
int minlen=1<<30,minlen0=0,totalcost=0;//分别为最短距离,此次探索的最短距离,总花费
int flag[101];//插旗记录是否走过
int minl[101][10001];//剪枝4用到此数组,意义是花费相同的金钱走到相同的城市所走的最短距离
void find(int s){
	if(s==n){
		if(minlen0<minlen)minlen=minlen0;//如果到达n城市
		return ;
	}
	for(int i=0;i<g[s].size();i++){
		road r=g[s][i];//遍历整个由s起始的路
		if(totalcost+r.money>k)continue;//剪枝1:钱不够
		if(flag[r.end])continue;//剪枝2:已经走过
		if(minlen0+r.len>minlen)continue;//剪枝3:当前走的距离已经超过了之前的最短距离
		if(minl[r.end][totalcost+r.money]<=minlen0+r.len)continue;//剪枝4:花费同样的价格走到了相同的城市,走的路比上一次花费同样的价格到这里要长
		minl[r.end][totalcost+r.money]=minlen0+r.len;//如果不则更新此数组
		minlen0+=r.len;
		totalcost+=r.money;
		flag[r.end]=1;
		find(r.end);
		minlen0-=r.len;//找完要退档
		totalcost-=r.money;
		flag[r.end]=0;
	}
}
int main(){
	cin>>k>>n>>t;
	for(int i=0;i<t;i++){
		int beg;
		road r;
		cin>>beg>>r.end>>r.len>>r.money;
		if(beg!=r.end)g[beg].push_back(r);
	}
	memset(flag,0,sizeof(flag));
	memset(minl,1<<30,sizeof(minl));
	flag[1]=1;
	find(1);
	if(minlen==1<<30)cout<<"-1";
	else cout<<minlen;
}

思路:深度搜索问题,用全局变量记录所走距离;

小技巧:

1.设置无穷大的数可以用:1<<30操作;

2.vector的使用(详见:C++vector容器详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值