zoukankan      html  css  js  c++  java
  • 【POJ3635】Full Tank 优先队列BFS

    普通BFS:每个状态只访问一次,第一次入队时即为该状态对应的最优解。
    优先队列BFS:每个状态可能被更新多次,入队多次,但是只会扩展一次,每次出队时即为改状态对应的最优解。
    且对于优先队列BFS来说,每次存入队列的不光是像普通BFS的状态,还有当前状态对应的代价,并且是依据最小代价进行扩展。每次状态被更近之后,将其入队。

    对于本题来说
    状态选取:当前所在城市,当前油量
    代价函数:当前状态所对应的最小花费

    代码如下:

    #include <cstdio>
    #include <iostream>
    #include <utility>
    #include <algorithm>
    #include <queue>
    #include <memory.h>
    #define cls(a,b) memset(a,b,sizeof(a))
    using namespace std;
    
    inline int read(){
    	int x=0,f=1;char ch;
    	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    	do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    	return f*x;
    }
    
    int d[1001][101],cost[1001];
    bool vis[1001][101];
    int n,m,q;
    int c,st,ed;
    struct edge{
    	int to,w;
    	edge(int to=0,int w=0):to(to),w(w){}
    };
    vector<edge> G[1001];
    inline void add_edge(int from,int to,int w){
    	G[from].push_back(edge(to,w));
    	G[to].push_back(edge(from,w));
    }
    
    int bfs(){
    	priority_queue< pair<int,pair<int,int> > > q;//存代价和状态
    	cls(vis,0);cls(d,0x3f);
    	d[st][0]=0;q.push(make_pair(0,make_pair(st,0)));
    	while(q.size()){
    		int city=q.top().second.first,fuel=q.top().second.second;q.pop();
    		if(vis[city][fuel])continue;//每个状态只会被扩展一次
    
    		if(city==ed)return d[city][fuel];//每个状态出队扩展时,对应最优解
    
    		vis[city][fuel]=1;//记录状态是否被扩展
    
    		if(fuel<c&&d[city][fuel+1]>d[city][fuel]+cost[city]){//满足条件,并且可以更新最优解
    			d[city][fuel+1]=d[city][fuel]+cost[city];
    			q.push(make_pair(-d[city][fuel+1],make_pair(city,fuel+1)));
    		}
    		for(int i=0;i<G[city].size();i++){
    			int to=G[city][i].to,w=G[city][i].w;
    			if(fuel>=w&&d[to][fuel-w]>d[city][fuel]){
    				d[to][fuel-w]=d[city][fuel];
    				q.push(make_pair(-d[to][fuel-w],make_pair(to,fuel-w)));//负号为改大根堆为小根堆
    			}
    		}
    	}
    	return -1;
    }
    
    void read_and_parse(){
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)cost[i]=read();
    	for(int i=1;i<=m;i++){
    		int from=read()+1,to=read()+1,w=read();
    		add_edge(from,to,w);
    	}
    }
    
    void solve(){
    	q=read();
    	while(q--){
    		c=read(),st=read()+1,ed=read()+1;
    		int ans=bfs();
    		if(ans==-1)puts("impossible");
    		else printf("%d
    ",ans);
    	}
    }
    
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    bootstrap-select用法详解
    启动react项目报如下错误
    什么?女朋友生气哄不好?那是你没有这款神器!
    Python竟然能做这种进度条,看完别说WC!
    看完学习Python的萌新都在问的六个问题,你就可以毕业了!
    批量加水印防抄袭,Python轻松搞定!
    hdu_1272_小希的迷宫_201403091527
    hdu_1856_More is better_201403091720
    hdu_1213_How Many Tables_201403091126
    hdu_1232_畅通工程_201403091018
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/9800471.html
Copyright © 2011-2022 走看看