Low Cost Air Travel UVALive - 3561
2017-05-23 08:30
302 查看
Low Cost Air Travel UVALive - 3561
图论·最短路题目大意:
有一些联票,每张票有一些站,每张票你只能从头开始乘,不能不能中途上或者下。现在有一些行程,要按顺序去一些地方。问你怎么样乘花费最小。输出最小值和路径。题解:
由于联票的存在,不能用相邻两个城市的最短路求和了,因为几个连续的城市可能在用同一张联票。解决方法是把当前已经走了行程单上的前pos个城市作为状态的一部分,a表示当前在a城市,(pos,a)作为节点。
由于联票只能从头开始并在后面的任意一个地方下车,因此想到从第一站依次向后面的站点连边。枚举到达第一个城市是已经经过了多少城市visited,然后顺着联票走,计算相应的pos,连边。
最后跑dij即可。记录一下方案。
Code:
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <vector> #include <map> #include <stack> #define D(x) cout<<#x<<" = "<<x<<" " #define E cout<<endl #define MP make_pair using namespace std; const int N = 1005; const int M = 10005; const int INF = 0x3f3f3f3f; int NI,NT; int ticketcost ,ticketlen ; int listlen; vector<int> list; vector<int> ticket ; map<int,int> cityID; int reID ; int IDcnt; pair<pair<int,int>,int> pre[15] ; int ID(int x){ if(!cityID.count(x)) cityID[x]=++IDcnt, reID[IDcnt]=x; return cityID[x]; } struct Edge{ int apos,a,bpos,b,next,w,id; }e[M*2]; int head[15] ,ec=0; void edgeClear(){ memset(head,0,sizeof(head)); ec=0; } void add(int apos,int a,int bpos,int b,int w,int id){ //D(a); D(b); D(w); E; ec++; e[ec].apos=apos; e[ec].a=a; e[ec].bpos=bpos; e[ec].b=b; e[ec].w=w; e[ec].id=id; e[ec].next=head[apos][a]; head[apos][a]=ec; } void clearAll(){ IDcnt=0; cityID.clear(); edgeClear(); } struct Node{ int pos,a,val; Node(int _p,int _a,int _v){ pos=_p; a=_a; val=_v; } bool operator < (const Node &tp) const { return val > tp.val; } }; int d[15] ,done[15] ; int dij(int S,int T){ memset(done,0,sizeof(done)); memset(d,0x3f,sizeof(d)); memset(pre,-1,sizeof(pre)); priority_queue<Node> q; d[0][S]=0; q.push(Node(0,S,0)); while(!q.empty()){ Node u=q.top(); q.pop(); //D(u.a); D(u.pos); D(u.val); E; if(done[u.pos][u.a]) continue; done[u.pos][u.a]=1; for(int i=head[u.pos][u.a];i;i=e[i].next){ Node v=Node(e[i].bpos,e[i].b,u.val+e[i].w); //cout<<" "; D(v.a); D(v.pos); D(v.val); E; if(d[v.pos][v.a] > u.val+e[i].w){ d[v.pos][v.a]=u.val+e[i].w; pre[v.pos][v.a]=MP(MP(u.pos,u.a),e[i].id); q.push(v); } } } return d[listlen-1][list[list.size()-1]]; } void init(){ edgeClear(); for(int tic=0;tic<NT;tic++){ for(int visited=0;visited<listlen-1;visited++){ int pos=visited; for(int i=1;i<ticketlen[tic];i++){ if(ticket[tic][i]==list[pos+1]) pos++; add(visited,ticket[tic][0],pos,ticket[tic][i],ticketcost[tic],tic); } } } } int main(){ freopen("a.in","r",stdin); int cas=0; while(scanf("%d",&NT)==1 && NT){ clearAll(); ++cas; for(int i=0;i<NT;i++){ scanf("%d%d",&ticketcost[i],&ticketlen[i]); int x; ticket[i].clear(); for(int j=0;j<ticketlen[i];j++){ scanf("%d",&x); x=ID(x); ticket[i].push_back(x); } } scanf("%d",&NI); for(int i=0;i<NI;i++){ scanf("%d",&listlen); list.clear(); int x; for(int j=0;j<listlen;j++){ scanf("%d",&x); list.push_back(ID(x)); //list.push_back(x); } init(); int ans=dij(list[0],list[list.size()-1]); printf("Case %d, Trip %d: Cost = %d\n",cas,i+1,ans); printf(" Tickets used:"); int pos=listlen-1, u=list[list.size()-1]; stack<int> s; while(pos>=0){ s.push(pre[pos][u].second+1); pair<int,int> tp=pre[pos][u].first; pos=tp.first; u=tp.second; } s.pop(); while(!s.empty()){ printf(" %d",s.top()); s.pop(); } puts(""); } } }
相关文章推荐
- UVALive 3561 Low Cost Air Travel(多状态最短路,dp)
- UVA 1048 - Low Cost Air Travel(最短路)
- uva 1048 - Low Cost Air Travel(最短路)
- la 3561 Low Cost Air Travel
- UVA 1048 Low Cost Air Travel
- Uvalive 6302 Star Travel
- 文章标题 UVALive 6062:Reduce the Maintenance Cost(双联通分量缩点)
- UVALive 6904 Travel Card(dp)
- UVALive 5862 City Travel 解题报告
- UVALive 7483 Air Conditioned Minions
- uvalive 3989 Ladies' Choice 稳定婚姻问题
- UVALive - 6455 Stealing Harry Potter's Precious (bfs+dfs)
- UVALive - 4108 SKYLINE (线段树的区间修改)
- UVALive 2678 子序列
- UVALive 4264 Message (模拟)
- 【UVALive】3029.City Game<C++>
- UVALive 6854 City(构造)
- UVALive 6656 Watching the Kangaroo --二分
- UVALive 6661 Equal Sum Sets
- UVALive 6042 Bee Tower(DP)