圖中每條路都有 路長 和 “過路費” 兩個參數,現在只有 K 塊錢,要你求起點到終點的最短路,也就是說在 K 花費內的最短路。
這個題其實很多解的,只不過是題目描述用的模型是最短路的模型,其實方法多種多樣。
深搜解:每次找滿足 花費 限制的點操作;總路長變長那麼就回溯;遞迴出口是找到終點。
#include<cstdio>#include<cstring>const int N = 1010;const int INF = 1e6;struct Edge{int s,e,len,cost;int next;}edge[10*N];int n,m,e_num,head[N],vis[N];int ans;void AddEdge(int a,int b,int c,int d){edge[e_num].s=a; edge[e_num].e=b; edge[e_num].len=c; edge[e_num].cost=d;edge[e_num].next=head[a]; head[a]=e_num++;}void dfs(int id,int dist,int money){//當前點的下標,當前離開起點的距離,還剩下的前if(dist>ans)return;//如果距離變大的話,回溯if(id==n && money>=0 && dist<ans) ans=dist;//到達終點賦值for(int i=head[id];i!=-1;i=edge[i].next){int u=edge[i].e;if(!vis[u] && money >= edge[i].cost){vis[u]=1;dfs(u,dist+edge[i].len,money-edge[i].cost);vis[u]=0;}}}int main(){int i,a,b,c,d,k;while(~scanf("%d%d%d",&k,&n,&m)){e_num=0;memset(head,-1,sizeof(head));for(i=0;i<m;i++){scanf("%d%d%d%d",&a,&b,&c,&d);AddEdge(a,b,c,d);}ans=INF;memset(vis,0,sizeof(vis));dfs(1,0,k);printf(ans<INF?"%d\n":"-1\n",ans);}return 0;}
dij + heap 解:取最近的且滿足 花費 限制的點入隊
#include<cstdio>#include<cstring>#include<queue>using namespace std;const int N = 105;const int INF = 1e6;struct node{int id,cost,dis;bool operator < (const node &a) const{return a.dis<dis;}};struct Edge{int e,len,cost;int next;}edge[10005];int n,k,e_num,head[N];void AddEdge(int a,int b,int c,int d){edge[e_num].e=b; edge[e_num].len=c; edge[e_num].cost=d;edge[e_num].next=head[a]; head[a]=e_num++;}void dij(){int i;node cur,next;priority_queue <node> q;cur.id=1; cur.dis=0; cur.cost=0;q.push(cur);int ans=INF;while(!q.empty()){cur=q.top();//取最近的點出隊q.pop();if(cur.id==n){ans=cur.dis;break;}for(i=head[cur.id];i!=-1;i=edge[i].next){if(cur.cost+edge[i].cost<=k){//滿足條件限制情況下的最短路next.id=edge[i].e;next.dis=edge[i].len+cur.dis;next.cost=edge[i].cost+cur.cost;q.push(next);}}}printf(ans<INF?"%d\n":"-1\n",ans);}int main(){int a,b,c,d,m;while(~scanf("%d%d%d",&k,&n,&m)){e_num=0;memset(head,-1,sizeof(head));while(m--){scanf("%d%d%d%d",&a,&b,&c,&d);AddEdge(a,b,c,d);}dij();}return 0;}