#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
using namespace std;
struct Roads
{
int d;
int l;
int t;
};
vector<Roads> city[105]; //定义向量,相当于一个二维数组,其中第一维的长度无限大,第二维的长度是105,数组中的各个元素是之前定义的Roads结构体
int K,N,R;
int totallen,totalcost,minlen;
int minn[105][10005]; //minn[i][j]表示到达i城市且花费了j时所走的最小路程 ,用于下面每走到一个城市都可以进行剪枝
int visited[105]; //由于本题是求最短路径长度,而若是走的过程中,对一个城市走了不止一遍,那么肯定不再是最短路径长度,所以每一个城市都不可以重复走
void dfs( int c )
{
if( c == N ) //走到了终点
{
minlen = min( minlen , totallen ); //结束递归之前,先更新minlen的值
return ;
}
int rnum = city[c].size();
for( int i = 0 ; i < rnum ; ++i ) //遍历c城市所能走的所有路
{
if( visited[city[c][i].d] || totalcost + city[c][i].t > K ) //可行性剪枝
continue;
if( totallen + city[c][i].l >= minlen || totallen + city[c][i].l >= minn[city[c][i].d][totalcost + city[c][i].t] ) //最优性剪枝
continue;
totalcost += city[c][i].t;
totallen += city[c][i].l;
minn[city[c][i].d][totalcost] = totallen;
visited[city[c][i].d] = 1; //更新状态
dfs(city[c][i].d);
totallen -= city[c][i].l;
totalcost -= city[c][i].t;
visited[city[c][i].d] = 0; //还原状态
}
}
int main()
{
freopen( "E:\\in.txt", "r" , stdin );
cin >> K; //总共的钱
cin >> N >> R;
for(int i = 0; i < R ; ++i) //构建图(连接表)
{
int s;
cin>>s;
Roads r;
cin>>r.d>>r.l>>r.t;
city[s].push_back(r);
}
totalcost = 0; //初始化
totallen = 0;
minlen = 1 << 30;
for(int i = 0 ; i < 105 ; ++i)
for(int j = 0 ; j < 10005 ; ++j)
minn[i][j] = 1 << 30;
memset(visited,0,sizeof(visited));
dfs(1); //深搜开始
if(minlen == 1 << 30) //minlen的值没有被改变 说明并没有找到合适的路
cout << "-1" << endl;
else
cout << minlen << endl;
return 0;
}
Poj 1724 Roads(DFS 可行性剪枝 最优性剪枝 向量)
最新推荐文章于 2022-01-09 22:54:24 发布