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容器详解)