#6177. 「美团 CodeM 初赛 Round B」送外卖2(floyed + 三进制枚举 )

 题目大意:

一张  个点  条有向边的图上,有  个配送需求,需求的描述形式为 ,即需要从点  送到 , 在时刻  之后(包括  )可以在  领取货物,需要在时刻  之前(包括 )送达  ,每个任务只需完成一次。

图上的每一条边均有边权,权值代表通过这条边消耗的时间。在时刻  有一个工作人员在点  上,求他最多能完成多少个配送任务。

在整个过程中,可以认为领货跟交货都是不消耗时间的,时间只花费在路程上。当然在一个点逗留也是允许的。

具体思路:

首先对全图跑一个floyed,求一下各点之间的最短路。 然后分析每一个运送路线,三进制枚举,0表示当前的货物是没有取,1表示当前的货物是在路上的,2表示已经送达。

dp[i][j]表示当前在i点所有路线的送货状态为j时的最小花费。

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define inf 0x3f3f3f3f
 5 #define LL_inf (1ll << 60)
 6 const int maxn = 20 + 5;
 7 const int mod = 1e9 + 7;
 8 int n, m, q;
 9 int dis[maxn][maxn];
10 struct node {
11     int s, t, l, r;
12 } sto[15];
13 void floyed() {
14     for (int i = 1; i <= n; i++) {
15         for (int j = 1; j <= n; j++) {
16             for (int k = 1; k <= n; k++) {
17                 dis[j][k] = min(dis[j][k], dis[j][i] + dis[i][k]);
18             }
19         }
20     }
21 }
22 int third[maxn];
23 int dp[maxn][60005];
24 void solve(int maxstate) {
25     memset(dp, inf, sizeof(dp));
26     dp[1][0] = 0;
27     for (int i = 0; i <= maxstate; i++) {
28         for (int j = 1; j <= n; j++) {
29             for (int k = 1; k <= q; k++) {
30                 int tmp = i % third[k + 1] / third[k];
31                 if (tmp == 0 && dp[j][i] + dis[j][sto[k].s] <= sto[k].r) {
32                     dp[sto[k].s][i + third[k]] =
33                         min(dp[sto[k].s][i + third[k]], max(sto[k].l, dp[j][i] + dis[j][sto[k].s]));// 注意这里应该取最大值,有可能到了还没到规定的取货时间
34                 }
35                 if (tmp == 1 && dp[j][i] + dis[j][sto[k].t] <= sto[k].r) {
36                     dp[sto[k].t][i + third[k]] = min(dp[sto[k].t][i + third[k]], dp[j][i] + dis[j][sto[k].t]);
37                 }
38             }
39         }
40     }
41 }
42 int main() {
43     scanf("%d %d %d", &n, &m, &q);
44     for (int i = 1; i <= n; i++) {
45         for (int j = 1; j <= n; j++) {
46             if (i == j)
47                 dis[i][j] = 0;
48             else
49                 dis[i][j] = inf;
50         }
51     }
52     int st, ed, val;
53     while (m--) {
54         scanf("%d %d %d", &st, &ed, &val);
55         dis[st][ed] = min(dis[st][ed], val);
56     }
57     for (int i = 1; i <= q; i++) {
58         scanf("%d %d %d %d", &sto[i].s, &sto[i].t, &sto[i].l, &sto[i].r);
59     }
60     floyed();
61     third[1] = 1;
62     for (int i = 2; i <= q + 1; i++) {
63         third[i] = third[i - 1] * 3;
64     }
65     solve(third[q + 1] - 1);
66     int ans = 0;
67     for (int i = 1; i <= n; i++) {
68         for (int j = 0; j <= third[q + 1] - 1; j++) {
69             if (dp[i][j] >= inf)
70                 continue;
71             int tmp = 0;
72             for (int k = 1; k <= q; k++) {
73                 tmp += ((j % third[k + 1] / third[k]) == 2 ? 1 : 0);
74             }
75             ans = max(ans, tmp);
76         }
77     }
78     printf("%d\n", ans);
79     return 0;
80 }

 

posted @ 2019-06-20 16:51  Let_Life_Stop  阅读(289)  评论(0编辑  收藏  举报