1. 程式人生 > >tyvj2032(超級源點)

tyvj2032(超級源點)

struct 註意 i++ operator 背景 現在 mat top 之間

題目背景

開啟了升降梯的動力之後,探險隊員們進入了升降梯運行的那條豎直的隧道,映入眼簾的是一條直通塔頂的軌道、一輛停在軌道底部的電梯、和電梯內一桿控制電梯升降的巨大手柄。

題目描述

Nescafe 之塔一共有N 層,升降梯在每層都有一個停靠點。手柄有M個控制槽,第i 個控制槽旁邊標著一個數Ci,滿足C1<C2<C3<??<CM。如果Ci>0,表示手柄扳動到該槽時,電梯將上升Ci 層;如果Ci<0,表示手柄扳動到該槽時,電梯將下降-Ci 層;並且一定存在一個Ci=0,手柄最初就位於此槽中。註意升降梯只能在1到N 層間移動,因此扳動到使升降梯移動到1 層以下、N 層以上的控制槽是不允許的。

電梯每移動一層,需要花費2 秒鐘時間,而手柄從一個控制槽扳到相鄰的槽,需要花費1 秒鐘時間。探險隊員現在在1 層,並且想盡快到達N 層,他們想知道從1 層到N 層至少需要多長時間?

輸入輸出格式

輸入格式:

第一行兩個正整數 N、M。

第二行M 個整數C1、C2??CM。

輸出格式:

輸出一個整數表示答案,即至少需要多長時間。若不可能到達輸出-1。

輸入輸出樣例

輸入樣例#1:
6 3
-1 0 2
輸出樣例#1:
19

說明

對於30% 的數據,滿足1≤N≤ 10; 2≤M≤ 5。

對於100% 的數據,滿足1≤N≤1000; 2 ≤ M ≤20;-N < C1 <C2 < …… < CM < N。

樣例解釋

手柄從第二個槽扳到第三個槽(0 扳到2),用時1 秒,電梯上升到3層,用時4 秒。

手柄在第三個槽不動,電梯再上升到5 層,用時4 秒。

手柄扳動到第一個槽(2 扳到-1),用時2 秒,電梯下降到4 層,用時2 秒。

手柄扳動到第三個槽(-1 扳倒2),用時2 秒,電梯上升到6 層,用時4 秒。

總用時為(1+4)+4+(2+2)+(2+4)=19 秒。

把電梯處於每層,控制器處於哪個控制槽當做狀態編號

把可行狀態之間連邊

最後把m個終止狀態連向同一個源點,即建造一個超級源求最短路即可

#include<cstdio>
#include<algorithm>
#include
<cstring> #include<cmath> #include<queue> using namespace std; struct my{ int v; int next; int w; }; struct head{ int u,w; bool operator <(const head &rhs)const{ return w>rhs.w; } }; const int maxn=10000+10; const int maxm=1e6+10; const int nil=0x7f7f7f7f; int c[maxn],fa,n,m,adj[maxm],d[maxm]; bool done[maxm]; my bian[2*maxm]; priority_queue<head>Q; void myinsert(int u,int v,int w){ bian[++fa].v=v; bian[fa].next=adj[u]; bian[fa].w=w; adj[u]=fa; } int id(int x,int y){ return (x-1)*m+y; } void dij(int s){ for (int i=1;i<=n*m+1;i++) d[i]=nil; head x; x.u=s; x.w=0; d[s]=0; Q.push(x); while(!Q.empty()){ x=Q.top();Q.pop(); int u=x.u; if(done[u]) continue; done[u]=true; for (int i=adj[u];i;i=bian[i].next){ int v=bian[i].v; int w=bian[i].w; if(d[v]>d[u]+w){ d[v]=d[u]+w; x.u=v; x.w=d[v]; Q.push(x); } } } } int main(){ int top=0; scanf("%d%d",&n,&m); for (int i=1;i<=m;i++){ scanf("%d",&c[i]); if(c[i]==0) top=i; } for (int i=1;i<=n;i++){ for (int j=1;j<=m;j++){ if(j<m) myinsert(id(i,j),id(i,j+1),1); if(j>1) myinsert(id(i,j),id(i,j-1),1);//位於第i層第j個控制器可以連向另一個控制器 if(i+c[j]<=n&&i+c[j]>=1){ myinsert(id(i,j),id(i+c[j],j),abs(c[j]*2));//位於第i層第j個控制器,可以把電梯升至i+c[j]層 } } } for(int i = 1; i <= m; i++) myinsert(id(n, i), n * m + 1, 0);//把m個終止狀態連向同一個源點,即建造一個超級源 dij(id(1,top)); if(d[n*m+1]>=nil) printf("-1"); else printf("%d",d[n*m+1]); return 0; }

tyvj2032(超級源點)