7-4 Helping the Couriers (30 分)

7-4 Helping the Couriers (30 分)

Gao recently took a part time job as a courier(快递员). Every time as he picks up N packages from the distribution center, he would always try to find the best way to deliver those packages so that he can finish this round as quickly as possible. On the other hand, as a programmer, Gao understands that finding the simple cycle that visits all the vertices with the minimum time is an NP hard problem. So he wouldn’t ask you to find the best solution for him. Instead, he would give you several plans to check, and you are supposed to tell him the best plan.

What makes this job a little bit complicated is that every package has a deadline for delivery. If Gao can deliver the package in time, he will receive Y yuans payment; or if he misses the deadline, he will be penalized and lose P yuans after gaining Y yuans payment. He would choose the plan that can gain him the most amount of payment first. If there are more than one choices, he would pick the one with the minimum total time of delivery.

It is assumed that Gao would always choose the shortest path between any pair of destinations, but he will NOT deliver any package on the way along the shortest path.

Input Specification:
Each input file contains one test case. For each case, the first line gives two positive numbers and a time: N (≤10^3) which is the total number of packages, M, the number of streets among those delivery points, and the starting time of the delivery tour, in the format hh:mm where hh is the hour and mm is the minute, and the time is in the range from 08:00 to 17:00. Here we assume that the package delivery points are numbered from 1 to N and the distribution center is numbered 0.

Then N lines follow. The ith line gives the information of the ith package, in the format

deadline Y P
where deadline is the deadline for delivery and is also in hh:mm. It is assumed that all the deadlines are in [00:00, 23:59] within the same day of the starting time; Y is the payment for successfully delivering this package no later than the deadline; and P is the penalty for missing the deadline, both are no more than 10^4

And then M lines follow, each describes a street in the format

V1 V2 time
where V1 and V2 are the indices of the two ends of this street, and time is the minutes (≤120) taken to pass this street. It is guaranteed that Gao can reach every delivery point, either directly or indirectly.
Finally there is a positive integer K (≤100) followed by K lines of plans, each contains N indices corresponding to an order of delivery. It is assumed that Gao always starts from 0 and returns to 0, hence 0 is not explicitly given in the input plan. The numbers in a line are separated by spaces.

Output Specification:
Among all the given plans, find the plan with the maximum payment that Gao can gain and the minimum time taken for him to complete this round of delivery. Print in a line the payment and the time he gets back to the distribution center (in the format hh:mm). The numbers must be separated by exactly 1 space and there must be no extra space at the beginning or the end of the line.

By the way, you must ignore those plans that are impossible for Gao to finish his job. On the other hand, it is guaranteed that there is at least one plan that is feasible.

Sample Input:

5 11 08:00
09:00 10 2
08:30 50 10
13:00 5 1
08:35 20 3
08:30 200 80
1 0 5
0 2 30
3 0 20
0 4 40
4 5 5
1 4 21
1 3 60
1 2 30
2 3 10
3 4 2
2 4 60
5
1 4 5 3 2
3 4 5 2 1
3 4 5 1 2
5 1 2 3 1
5 4 1 3 2

Sample Output:

275 09:53

思路:
floyd就行,注意下面几个点:
1、每个点必须走一次,否则排除此计划
2、不可到达的点排除
3、得到的钱初始化要足够小因为可能存在负数
4、时间要%24,因为可能不是当天完成

#include <iostream> 
#include <cstring>
using namespace std;
const int inf = 0x3f3f3f3f;
struct node{
	int time, y, p;
}a[1010];
int map[1010][1010], n, vis[1010];
void flody(){
	for(int k = 0; k <= n; ++k)
		for(int i = 0; i <= n; ++i)
			for(int j = 0; j <= n; ++j)
				map[i][j] = min(map[i][j], map[i][k] + map[k][j]);
}
int main() {
	int m, k, start, x, y, z, maxp = -999999999, mint = 999999999;
	scanf("%d%d", &n, &m);
	memset(map, inf, sizeof map);
	for(int i = 0; i <= n; ++i)
		map[i][i] = 0;
	scanf("%d:%d", &x, &y);
	start = x * 60 + y;
	for(int i = 1; i <= n; ++i){
		scanf("%d:%d", &x, &y);
		a[i].time = x * 60 + y;
		scanf("%d%d", &a[i].y, &a[i].p);
	}
	while(m--) {
		scanf("%d%d%d", &x, &y, &z);
		map[x][y] = map[y][x] = min(map[x][y], z);
	}
	flody();
	scanf("%d", &k);
	while(k--) {
		memset(vis, 0, sizeof vis);
		int now = start, pay = 0, f = 1;
		x = 0;
		for(int i = 0; i < n; ++i){
			scanf("%d", &y);
			if(f == 0) continue;
			if(vis[y] || map[x][y] == inf) f = 0;
			if(now + map[x][y] <= a[y].time) {
				pay += a[y].y;
			}
			else {
				pay += a[y].y - a[y].p;
			}
			now += map[x][y];
			vis[y] = 1;
			x = y;
		}
		if(f == 0) continue;
		now += map[x][0];
		if(pay > maxp) {
			maxp = pay;
			mint = now;
		}
		else if(pay == maxp && now < mint) {
			mint = now;
		}
	}
	printf("%d %02d:%02d", maxp, (mint/60) % 24, mint % 60);
} 
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值