1476:Always On the Run

题目

描述

Screeching tires. Searching lights. Wailing sirens. Police cars everywhere. Trisha Quickfinger did it again! Stealing the `Mona Lisa' had been more difficult than planned, but being the world's best art thief means expecting the unexpected. So here she is, the wrapped frame tucked firmly under her arm, running to catch the northbound metro to Charles-de-Gaulle airport.
But even more important than actually stealing the painting is to shake off the police that will soon be following her. Trisha's plan is simple: for several days she will be flying from one city to another, making one flight per day. When she is reasonably sure that the police has lost her trail, she will fly to Atlanta and meet her `customer' (known only as Mr. P.) to deliver the painting.

Her plan is complicated by the fact that nowadays, even when you are stealing expensive art, you have to watch your spending budget. Trisha therefore wants to spend the least money possible on her escape flights. This is not easy, since airlines prices and flight availability vary from day to day. The price and availability of an airline connection depends on the two cities involved and the day of travel. Every pair of cities has a `flight schedule' which repeats every few days. The length of the period may be different for each pair of cities and for each direction.

Although Trisha is a good at stealing paintings, she easily gets confused when booking airline flights. This is where you come in.
 

输入

The input contains the descriptions of several scenarios in which Trisha tries to escape. Every description starts with a line containing two integers n and k. n is the number of cities through which Trisha's escape may take her, and k is the number of flights she will take. The cities are numbered 1, 2, ..., n, where 1 is Paris, her starting point, and n is Atlanta, her final destination. The numbers will satisfy 2 <= n <= 10 and 1 <= k <= 1000.
Next you are given n(n - 1) flight schedules, one per line, describing the connection between every possible pair of cities. The first n - 1 flight schedules correspond to the flights from city 1 to all other cities (2, 3, ..., n), the next n - 1 lines to those from city 2 to all others (1, 3, 4, ..., n), and so on.

The description of the flight schedule itself starts with an integer d, the length of the period in days, with 1 <= d <= 30. Following this are d non-negative integers, representing the cost of the flight between the two cities on days 1, 2, ..., d. A cost of 0 means that there is no flight between the two cities on that day.

So, for example, the flight schedule "3 75 0 80" means that on the first day the flight costs 75, on the second day there is no flight, on the third day it costs 80, and then the cycle repeats: on the fourth day the flight costs 75, there is no flight on the fifth day, etc.

The input is terminated by a scenario having n = k = 0.
 

输出

For each scenario in the input, first output the number of the scenario, as shown in the sample output. If it is possible for Trisha to travel k days, starting in city 1, each day flying to a different city than the day before, and finally (after k days) arriving in city n, then print "The best flight costs x.", where x is the least amount that the k flights can cost.

If it is not possible to travel in such a way, print "No flight possible.".

Print a blank line after each scenario.

分析

这道题的输入首先是一行n和k,然后是n(n-1)行,每一行代表一趟航班,第一个数为d,表示费用循环周期,接下来d个数,其中第i个表示第i天该趟航班的费用,为0表示没有航班。输入以n=k=0结束。输出旅行k天最后到达第n个城市的最小费用。

这是一道比较明显的动规题,主要就是弄懂题目意思比较麻烦。按照输出中的要求,一个符合题意的路线需要满足以下几个要求:

1、从第1个城市出发

2、最终到达第n个城市

3、每一天进行一次飞行,共飞行k次

考虑定义一个结构体flight,用flight f[i][j]表示从第i个城市去往第j个城市的航班费用情况,其中包含循环天数d,每天的费用cost;用dp[i][j]来表示第i天在第j个城市的情况下,接下来的最小费用。注意到

dp[i][j]=min(cost[j][k]+dp[i+1][k]),(k!=j)

根据以上分析,不难得出代码:

#include<iostream>
#include<string>
#include<string.h>
#include<cmath>
#include<iomanip>
using namespace std;

int scenario = 0;
int n, k;
class flight {
public:
	int d;//循环天数
	int cost[31];//每天的费用
};
flight f[11][11];
int dp[1010][11];//dp[i][j]表示第i天在第j个城市的情况下,接下来的最小费用
bool w[1010][11];
int get_least(int current_day, int current_position) {//current_day表示当前天数,current_position表示当前所在城市
	if (w[current_day][current_position]) {
		return dp[current_day][current_position];
	}
	if (current_day == k) {//如果天数为k,此时必须在第n个城市,否则该路线不合题意
		if (current_position == n - 1) {
			return 0;
		}
		else {
			return 1000000000;
		}
	}
	if (current_day == k - 1) {//如果天数为k-1,此时必须不在第n个城市,否则下一天无法到达第n个城市
		if (current_position == n - 1) {
			return 1000000000;
		}
		int cost = f[current_position][n - 1].cost[(current_day) % f[current_position][n - 1].d];
		if (cost == 0) {
			return 1000000000;
		}
		return cost;
	}
	dp[current_day][current_position] = 1000000000;
	for (int i = 0; i < n; i++) {
		if (i == current_position) {
			continue;
		}
		int cost = f[current_position][i].cost[(current_day) % f[current_position][i].d];
		if (cost == 0) {
			continue;
		}
		dp[current_day][current_position] = min(dp[current_day][current_position], cost + get_least(current_day + 1, i));
	}
	w[current_day][current_position] = 1;
	return dp[current_day][current_position];
}//遍历所有从current_position出发可以到达的城市

int main() {
	while (cin >> n >> k) {
		if (n == 0 && k == 0) {
			break;
		}
		memset(w, 0, sizeof(w));
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (i == j) {
					continue;
				}
				cin >> f[i][j].d;
				for (int k = 0; k < f[i][j].d; k++) {
					cin >> f[i][j].cost[k];
				}
			}
		}
		int tmp = get_least(0, 0);
		cout << "Scenario #" << ++scenario << endl;
		if (tmp == 1000000000) {
			cout << "No flight possible." << endl;
		}
		else {
			cout << "The best flight costs " << tmp << "." << endl;
		}
		cout << endl;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值