#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 }

原文地址:https://www.cnblogs.com/letlifestop/p/11059760.html

时间: 2024-08-03 09:27:01

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

「美团 CodeM 初赛 Round B」送外卖2---------------状压dp

题目描述 一张 n 个点 m 条有向边的图上,有 q  个配送需求,需求的描述形式为 (si,ti,li,ri)( s_i , t_i , l_i , r_i )(si?,ti?,li?,ri?),即需要从点 si 送到 ti, 在时刻 li 之后(包括 lil_ili? )可以在 sis_isi? 领取货物,需要在时刻 ri 之前(包括 ri)送达 ti ,每个任务只需完成一次. 图上的每一条边均有边权,权值代表通过这条边消耗的时间.在时刻 000 有一个工作人员在点 1 上,求他最多能完成多

「美团 CodeM 初赛 Round B」景区路线规划 概率DP

题意 游乐园被描述成一张 n 个点,m 条边的无向图(无重边,无自环).每个点代表一个娱乐项目,第 i 个娱乐项目需要耗费 ci 分钟的时间,会让小 y 和妹子的开心度分别增加 h1i ,h2i ,他们俩初始的开心度都是 0 .每条边代表一条路,第 i 条边连接编号为 xi , yi 的两个娱乐项目,从 xi 走到 yi 或者从 yi 走到 xi 耗费的时间都是 ti 分钟.小 y 和妹子预计在游乐园里玩 k 分钟.最开始的时候,小 y 和妹子会等概率的随机选择一个娱乐项目开始玩,每玩完一个项目

Loj #6164. 「美团 CodeM 初赛 Round A」数列互质

link : https://loj.ac/problem/6164 莫队傻题,直接容斥做. #include<bits/stdc++.h> #define maxn 100005 #define pb push_back using namespace std; vector<int> g[maxn]; struct ask{ int l,r,K,num,bl; bool operator <(const ask &u)const{ return bl==u.bl?

LibreOJ #6191. 「美团 CodeM 复赛」配对游戏

二次联通门 : LibreOJ #6191. 「美团 CodeM 复赛」配对游戏 /* LibreOJ #6191. 「美团 CodeM 复赛」配对游戏 概率dp 不是很懂为什么这样做... */ #include <cstdio> #include <iostream> const int BUF = 12312312; char Buf[BUF], *buf = Buf; inline void read (int &now) { for (now = 0; !isdi

「题解」「美团 CodeM 资格赛」跳格子

目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞定,最后无奈 \(90pts\) . 然而 \(T2\) 想到很多很奇怪的做法,结果正解在 \(28min\) 之内做出... 结果 \(T3\) 是本人最不擅长的伪期望,直接跳过,啥都没得. 来水一发 \(T1\) 的题解... 题目描述 点这里 考场思路 其实并没有什么十分特别的思路,就是一通乱

LiberOJ #6210. 「美团 CodeM 决赛」tree 树形DP

题目链接:点这里 题解: 需要证明,所求的路径一定是全部权值都为1或者,路径上权值至多有一个为2其余为1且权值2在路径中央. 然后树形DP 设定dp[i][0/1] 以1为根的情况下,以i 节点下子树走分别全1和 走一次2和剩余全走1 的最长链 每遍历一次子树,统计一次答案 下面给出代码 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000&qu

「美团 CodeM 资格赛」试题泛做

LibreOJ真是吼啊! 数码 推个式子,把枚举因数转为枚举倍数.然后就发现它是根号分段的.然后每一段算一下就好了. 1 #include <cstdio> 2 #include <cstring> 3 4 #define R register 5 typedef long long ll; 6 struct Data { 7 ll num[10]; 8 inline void clear() 9 { 10 memset(num, 0, 10 << 3); 11 } 1

「美团 CodeM 复赛」城市网络

https://loj.ac/problem/6192 内存限制:64 MiB   时间限制:500 ms标准输入输出 题目描述 有一个树状的城市网络(即 nnn 个城市由 n−1n-1n−1 条道路连接的连通图),首都为 111 号城市,每个城市售卖价值为 aia_ia?i?? 的珠宝. 你是一个珠宝商,现在安排有 qqq 次行程,每次行程为从 uuu 号城市前往 vvv 号城市(走最短路径),保证 vvv 在 uuu 前往首都的最短路径上. 在每次行程开始时,你手上有价值为 ccc 的珠宝(

#6085. 「美团 CodeM 资格赛」优惠券

题目描述 用last[x]表示对x进行的上一次操作的位置,vis[x]表示x是否在大楼内. Splay维护'?'的位置. 若x要进楼: 1.若x已在楼内,则去找last[x]到i之间是否有'?',若有,则可以把这个'?'当做是上一个x出楼,反之则 出现错误. 2.若x不在楼内,标记x在楼内. 若x要出楼: 1.若x在楼内,标记x不在楼内. 2.若x不在楼内,相同的去找last[x]到i之间是否有'?'. #include<complex> #include<cstdio> usin