7-4 Helping the Couriers

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 (≤103) 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 104.

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

Hint:

Plan 4 is obviously impossible since point 4 is not in. The arriving times and payments for other plans are show in the following table. Plan 3 and 5 both give the maximum payments, yet Plan 3 takes fewer time. Hence the answer is Plan 3 with payment 275 and completion time 09:53.

PlanTermV1V2V3V4V50
1arrival08:0508:2608:3108:3808:4809:18
1payment+10+20+200-80+5+50-10195
2arrival08:2008:2208:2708:4409:1409:19
2payment+5+20+200+50-10+10-2273
3arrival08:2008:2208:2708:5309:2309:53
3payment+5+20+200+10+50-10275
5arrival08:2708:3208:5309:1609:2609:56
5payment+200+20+10+5+50-10275

1 每个点都访问到且只访问一次

2 floyd求各点间的最短路,因为快递员每次都选择最短路进行送快递

3 max_pay可能是负数 所以要设置为-INF min_time可能超过一天所以要%24 

#include<iostream>
#include<cstring>
using namespace std;
const int N = 1010,INF = 0x3f3f3f3f;
int n,m,start_time;
int cost[N][N],min_time = INF,max_pay = -INF ;
bool suc=true;
bool st[N];
struct Package{
    int deadline;
    int y,p;
}pack[N];
void floyd(){
    for(int k = 0;k<=n;k++)
        for(int i = 0;i<=n;i++)
            for(int j = 0;j<=n;j++)
                cost[i][j] = min(cost[i][j],cost[i][k]+cost[k][j]);
}
int main(){
    int hh,mm;
    scanf("%d %d %d:%d",&n,&m,&hh,&mm);
    start_time = hh*60+mm;
    memset(cost,0x3f,sizeof cost);
    for(int i = 0;i<=n;i++)cost[i][i] = 0;
    for(int i = 1;i<=n;i++){
        int y,p;
        scanf("%d:%d %d %d",&hh,&mm,&y,&p);
        int deadline = hh*60+mm;
        pack[i] ={deadline,y,p};
    }
    for(int i = 0;i<m;i++){
        int a,b,c;cin>>a>>b>>c;
        cost[a][b] = cost[b][a] = min(cost[a][b],c);
    }
    floyd();
    int k;
    cin>>k;
    while(k--){
        int last = 0;
        int start = start_time;
        suc = true;
        memset(st,0,sizeof st);
        int pay = 0;
        st[0] = 1;
        for(int i = 1;i<=n;i++){
            int cur;cin>>cur;
            if(st[cur]||cost[last][cur]==INF) suc = false;
            if(!suc) continue;
            st[cur] = 1;
            if(start+cost[last][cur]<=pack[cur].deadline){
                pay+=pack[cur].y;
            }else{
                pay+=pack[cur].y-pack[cur].p;
            }
            start += cost[last][cur];
            last = cur;
        }
        if(!suc)continue;
        start+=cost[last][0];
        if(max_pay<pay){
            max_pay = pay;
            min_time = start;
        }else if(max_pay==pay&&min_time>start){
            min_time = start;
        }
    }
    hh = min_time/60%24,mm = min_time%60;
    printf("%d %02d:%02d",max_pay,hh,mm);
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值