1048 - Low Cost Air Travel

Air fares are crazy! The cost of a ticket is determined by numerous factors, and is usually not directly related to the distance traveled. Many travelers try to be creative, sometimes using only parts of tickets with stops in various cities to achieve lower-cost travel. However, the airlines are aware of this behavior, and usually require that the travel covered by a ticket be completed in order and without intervening travel. For example, if you have a ticket for travel from City-1 to City-2 then to City-3, you are not allowed to use only the portion of the ticket for travel from City-2 to City-3. You must always start at the first city on the ticket. In addition, you are not allowed to travel from City-1 to City-2, fly elsewhere and return, and then continue your journey from City-2 to City-3.


Let's consider an example. Suppose you are allowed to purchase three types of tickets:


Ticket #1:City-1 to City-3 to City-4$225.00
Ticket #2:City-1 to City-2$200.00
Ticket #3:City-2 to City-3$50.00


Suppose you wanted to travel from City-1 to City-3. There are two ways to get there using only the available ticket choices:


Purchase Ticket #1 for $225.00 and use only the first leg of the ticket.
Purchase Ticket #2 for $200.00 and Ticket #3 for $50.


The first choice is the cheapest.


Given a set of airline ticket offers, and one or more trip itineraries, you must determine how to purchase tickets in order to minimize the cost of travel. Each trip will be possible.

Input 

Input consists of multiple test cases, each describing a set of ticket offers and a set of trip itineraries.

Each case begins with a line containing NT, the number of ticket offers, followed by NT offer descriptions, one to a line. Each description consists of a positive integer specifying the price of the ticket, the number of cities in the ticket's route, and then that many cities. Each city in a case has an arbitrary, but unique, integer identification number. Note that several tickets may be purchased from the same offer.

The next line contains NI, the number of trips that are to have their cost minimized. NI lines follow, giving the itineraries for each trip. Each line consists of the number of cities in the itinerary (including the starting city), followed by that many city identification numbers, given in the order they are to be visited.

There will be no more than 20 ticket offers or 20 itineraries in a test case. Each offer and itinerary lists from 2 to 10 cities. No ticket price exceeds $10,000. Adjacent cities in a route or itinerary will be distinct. Tickets and trips are numbered sequentially in each set, starting with 1.

The last case is followed by a line containing a zero.

Output 

For each trip, output two lines containing the case number, the trip number, the minimum cost of the trip, and the numbers of the tickets used for the trip, in the order they will be used. Follow the output format shown below. The output will always be unique.

Sample Input 

3 
225 3 1 3 4 
200 2 1 2 
50 2 2 3 
1 
2 1 3 
3 
100 2 2 4 
100 3 1 4 3 
200 3 1 2 3 
2 
3 1 4 3 
3 1 2 4 
0

Sample Output 

Case 1, Trip 1: Cost = 225
  Tickets used: 1
Case 2, Trip 1: Cost = 100
  Tickets used: 2
Case 2, Trip 2: Cost = 300
  Tickets used: 3 1

Claimer: The data used in this problem is unofficial data prepared by Derek Kisman. So any mistake here does not imply mistake in the offcial judge data. Only Derek Kisman is responsible for the mistakes. Report mistakes to dkisman@acm.org







#include<stdio.h>
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 cases,NT,NI,i,j,k,l,tmp,trip,change,sum,n;
int city[Max_City];
int list[Max_TripLength];
info ticket[Max_Ticket];
int f[Max_TripLength][Max_City][4];

int route[Max_TripLength * 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()
{
	cases=0;
	while(1)
	{
		scanf("%d",&NT);
		sum=0;
		if(NT==0)
			break;
		else
			cases++;
		for(i=0;i<NT;i++)
		{
			scanf("%d %d",&ticket[i].cost,&ticket[i].n);
			for(j=0;j<ticket[i].n;j++)
			{
				scanf("%d",&tmp);
				ticket[i].city[j]=find(tmp);
			}
		}
		scanf("%d",&NI);
		for(trip=0;trip<NI;trip++)
		{
			scanf("%d",&n);
			for(i=0;i<n;i++)
			{
				scanf("%d",&tmp);
				list[i]=find(tmp);
			}
			for(i=0;i<n;i++)
				for(j=0;j<sum;j++)
					f[i][j][0]=-1;
			for(i=0;i<4;i++)
				f[0][list[0]][i]=0;
			for(i=0;i<n;i++)
			{
				while(1)
				{
					change=0;
					for(j=0;j<sum;j++) if(f[i][j][0]>=0)
						for(k=0;k<NT;k++) if(ticket[k].city[0]==j)
						{
							tmp=i+1;
							for(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++;
								}
							}
						}
					if(change==0)
						break;
				}
			}
			printf("Case %d, Trip %d: Cost = %d\n",cases,trip+1,f[n-1][list[n-1]][0]);
			l=0;
			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");
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值