POJ - 3635 Full Tank?(bfs)
題目鏈接:點(diǎn)擊查看
題目大意:給出一個(gè)無(wú)環(huán)無(wú)向圖,每個(gè)點(diǎn)都可以看做一個(gè)補(bǔ)給站,油價(jià)是固定的,每條路都要消耗一定的油量,給出q個(gè)詢問(wèn),問(wèn)油箱大小為c,從起點(diǎn)到終點(diǎn)所需要的最小花費(fèi)
題目分析:可以用bfs+優(yōu)先隊(duì)列直接爆搜,我們令每個(gè)狀態(tài)都是一個(gè)二元組(x,y)代表的是在x點(diǎn)剩y升油,則每個(gè)點(diǎn)(u,f)都可以更新為(u,f+1)和(v,f-w)兩個(gè)狀態(tài),因?yàn)閏給的很小,只有100,總的時(shí)間復(fù)雜度最差也是n*c*q=1000*100*100=1e7,在算上點(diǎn)常數(shù)時(shí)間開(kāi)銷,1秒跑完這個(gè)題也是穩(wěn)穩(wěn)的了。
優(yōu)先隊(duì)列中我維護(hù)了三個(gè)變量,分別是當(dāng)前節(jié)點(diǎn),當(dāng)前剩余油量,當(dāng)前花銷,對(duì)于花銷重載小于號(hào),這樣就能保證到達(dá)終點(diǎn)時(shí)的第一個(gè)點(diǎn)一定是最優(yōu)解。網(wǎng)上我看有的題解還用動(dòng)態(tài)規(guī)劃的思想維護(hù)了一個(gè)二維cost數(shù)組,用來(lái)記錄到x點(diǎn)時(shí)剩余油量為y的最小花費(fèi),我個(gè)人感覺(jué)沒(méi)必要,因?yàn)橛昧藘?yōu)先隊(duì)列后求出的答案一定是最優(yōu)解了,如果再同時(shí)維護(hù)一個(gè)cost數(shù)組就是給自己找麻煩,但換個(gè)想法,如果用cost數(shù)組搭配普通隊(duì)列或許會(huì)更快,前兩天也是做了一個(gè)題,就是需要維護(hù)一個(gè)數(shù)組來(lái)進(jìn)行條件判斷
因?yàn)榇a寫(xiě)的有點(diǎn)亂,湊活看吧,因?yàn)槎啻纬霈F(xiàn)了結(jié)構(gòu)體的調(diào)用,之后如果有空會(huì)再寫(xiě)寫(xiě)隊(duì)列+動(dòng)態(tài)規(guī)劃的形式,說(shuō)不定會(huì)快一點(diǎn)
直接上代碼了,優(yōu)先隊(duì)列+bfs:
#include<iostream> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e3+100;struct Node {int to,w,f;Node(int TO,int W){to=TO;w=W;f=0;}Node(int TO,int W,int F){to=TO;w=W;f=F;}bool operator<(const Node& a)const{return w>a.w;} };vector<Node>node[N];int n,m;int c,s,e;int ans;int p[N]; bool vis[N][N];bool bfs() {memset(vis,false,sizeof(vis));priority_queue<Node>q;q.push(Node(s,0,0));vis[s][0]=true;while(!q.empty()){Node cur=q.top();q.pop();if(cur.to==e){ans=cur.w;return true;}if(cur.f<c&&!vis[cur.to][cur.f+1]){ // vis[cur.to][cur.f+1]=true; //不要加這句話,會(huì)WA,因?yàn)関is記錄的是轉(zhuǎn)移過(guò)后的狀態(tài),這里雖然也是轉(zhuǎn)移狀態(tài) //但最多算是起點(diǎn)而不是終點(diǎn),換句話說(shuō),這里更新的狀態(tài)是讓cost變大,我們的目的是盡可能讓cost變小 //如果我們?cè)谶@里將cur.to,cur.f+1這個(gè)狀態(tài)標(biāo)記掉了,那么可能讓下面的最優(yōu)解無(wú)法遍歷到 //可以將這里的更新理解為初始化,然后后續(xù)肯定會(huì)有最優(yōu)解來(lái)更新掉這個(gè)答案 //我反正感覺(jué)這一句話是這個(gè)程序中最難想的一個(gè)點(diǎn)了。。可能是我太菜了q.push(Node(cur.to,cur.w+p[cur.to],cur.f+1));}for(int i=0;i<node[cur.to].size();i++){int u=cur.to;int v=node[cur.to][i].to;int w=node[cur.to][i].w;if(cur.f<w)continue;if(vis[v][cur.f-w])continue;vis[v][cur.f-w]=true;q.push(Node(v,cur.w,cur.f-w));}}return false; }int main() {while(scanf("%d%d",&n,&m)!=EOF){for(int i=0;i<n;i++){scanf("%d",p+i);node[i].clear();}while(m--){int u,v,w;scanf("%d%d%d",&u,&v,&w);node[u].push_back(Node(v,w));node[v].push_back(Node(u,w));}int q;scanf("%d",&q);while(q--){scanf("%d%d%d",&c,&s,&e);if(bfs())printf("%d\n",ans);elseprintf("impossible\n");}}return 0; }?
總結(jié)
以上是生活随笔為你收集整理的POJ - 3635 Full Tank?(bfs)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: POJ - 1475 Pushing B
- 下一篇: 区间1~n的异或值