UVA 1048 Low Cost Air Travel

来源:互联网 发布:肯德基麦当劳知乎 编辑:程序博客网 时间:2024/06/01 16:52

题目链接:https://vjudge.net/problem/UVA-1048

题意:给定一些联票,在给定一些行程,要求这些行程的最小代价

解法:


#include <bits/stdc++.h>using namespace std;const int Max_City = 200;const int Max_Ticket = 20;const int Max_TicketLength = 10;const int Max_TripLength = 10;struct Info{    int cost,n;    int city[Max_TicketLength];};int N, n, q, trip, sum;//路线编号为trip,sum为总的城市数,n为某条旅行路线的长度int city[Max_City];//城市序列int List[Max_TripLength];//当前最小旅游费用路线上第i个到达的城市为List[i]Info ticket[Max_Ticket];int f[Max_TripLength][Max_City][4];//途径当前路线的前n个城市,//最后到达城市m时,最小花费为f[n][m][0]//最后使用的机票编号为f[n][m][1],//使用本机票前途径的城市数为f[n][m][2],开始使用本机票的城市为f[n][m][3]int route[Max_TicketLength*Max_City];//当期路线使用的机票序列int Find(int x){    int i;    for(i=0;i<sum;i++) if(city[i]==x) return i;    city[sum]=x;    sum++;    return (sum-1);}int main(){    int ks = 0;    while(scanf("%d", &N)!=EOF){        if(N==0) break;        sum=0;        int tmp;        for(int i=0; i<N; i++){            scanf("%d %d", &ticket[i].cost,&ticket[i].n);            for(int j=0; j<ticket[i].n; j++){                scanf("%d", &tmp);                ticket[i].city[j] = Find(tmp);            }        }        ++ks;        scanf("%d", &q);        for(trip=0; trip<q; trip++){            scanf("%d", &n);            for(int i=0; i<n; i++){                scanf("%d", &tmp);                List[i] = Find(tmp);            }            //init            for(int i=0; i<n; i++)                for(int j=0; j<sum; j++)                    f[i][j][0] = -1;            for(int i=0; i<4; i++)                f[0][List[0]][i] = 0;            //递推路线上到达的城市数            for(int i=0; i<n; i++){                while(1){                    bool change = 0;//更新标志初始化                    for(int j=0; j<sum; j++)//枚举旅行者目前在的城市                        if(f[i][j][0]>=0)//若已经求出到城市j的最小花费                            for(int k=0; k<N; k++)//枚举在城市j开始换用的机票k                            if(ticket[k].city[0]==j){                                tmp=i+1;                                //从当前路线的第i+1个城市出发,枚举使用优惠机票k可到达路线上的每个城市                                for(int l=1;l<ticket[k].n; l++){                                    if(tmp<n&&List[tmp]==ticket[k].city[l]) tmp++;                                    if(f[tmp-1][ticket[k].city[l]][0]<0||f[tmp-1][ticket[k].city[l]][0]>f[i][j][0]+ticket[k].cost){                                        f[tmp-1][ticket[k].city[l]][0] = f[i][j][0]+ticket[k].cost;                                        f[tmp-1][ticket[k].city[l]][1] = k;                                        f[tmp-1][ticket[k].city[l]][2] = i;                                        f[tmp-1][ticket[k].city[l]][3] = j;                                        change=1;                                    }                                }                            }                    if(change==0) break;                }            }            printf("Case %d, Trip %d: Cost = %d\n", ks, trip+1, f[n-1][List[n-1]][0]);            int l=0;            int k,i=n-1,j=List[n-1];            while(i||j!=List[0]){                route[l]= f[i][j][1];//记下当前的机票编号                k = f[i][j][2];//记下使用本机票前到过的城市数                j = f[i][j][3];//记下使用本机票前旅行者在的城市                i = k;                l++;            }            printf("  Tickets used:");            for(i=l-1; i>=0; i--){                printf(" %d", route[i]+1);            }            printf("\n");        }    }}


原创粉丝点击