您的位置:首页 > 大数据 > 人工智能

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("");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: