2021年度训练联盟热身训练赛第三场(IH)
作者:互联网
I. Slow Leak(最短路)
题意:你有一辆轮胎会跑气的自行车,打满一次气可以走的距离是d,一开始自行车的气是满的,城市中有 n 个点,你要从1点到 n 点,其中有 t 个点处可以给自行车打气,你只能在自行车有气的时候走,问从1到 n 的最短路
思路:先跑一遍floyd求出每两点之间的最短路,然后重新构图,两个打气点之间的最短路 <= d时说明可以到达,否则不可以,然后再floyd || dijkstra求1到 n 的最短路。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const int N = 507;
const int M = 3e5 + 7;
bool vis[N];
int n, m, t, tot, head[N], ok[N];
ll d, mp[N][N], dis[N];
struct node {
int u, v, nxt;
ll w;
} edge[M];
struct A {
int pos;
ll cost;
bool operator < (const A &a) const {
return cost > a.cost;
}
};
void init() {
tot = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v, ll w) {
edge[tot].u = u;
edge[tot].v = v;
edge[tot].w = w;
edge[tot].nxt = head[u];
head[u] = tot++;
}
void floyd() {
for(int k = 1; k <= n; ++k) {
for(int i = 1; i <= n; ++i) {
mp[i][i] = 0;
for(int j = 1; j < i; ++j)
mp[i][j] = mp[j][i] = min(mp[i][j], mp[i][k] + mp[k][j]);
}
}
}
void dijkstra(int src) {
memset(dis, inf, sizeof(dis));
memset(vis, 0, sizeof(vis));
dis[src] = 0;
priority_queue<A>q;
q.push(A{src, 0});
while(!q.empty()) {
A now = q.top();
q.pop();
if(vis[now.pos]) continue;
vis[now.pos] = 1;
for(int i = head[now.pos]; ~i; i = edge[i].nxt) {
int u = edge[i].u, v = edge[i].v;
if(!vis[v] && dis[v] > dis[u] + edge[i].w) {
dis[v] = dis[u] + edge[i].w;
q.push(A{v, dis[v]});
}
}
}
}
int main() {
int u, v;
ll w;
scanf("%d%d%d%lld", &n, &m, &t, &d);
memset(mp, inf, sizeof(mp));
for(int i = 1; i <= t; ++i) scanf("%d", &ok[i]);
ok[t + 1] = 1, ok[t + 2] = n;
while(m--) {
scanf("%d%d%lld", &u, &v, &w);
if(mp[u][v] > w) mp[u][v] = mp[v][u] = w;
}
floyd();
init();
for(int i = 1; i <= t + 2; ++i) {
for(int j = i + 1; j <= t + 2; ++j) {
int u = ok[i], v = ok[j];
if(mp[u][v] <= d) addedge(u, v, mp[u][v]), addedge(v, u, mp[u][v]);
}
}
dijkstra(1);
if(dis[n] == inf) printf("stuck\n");
else printf("%lld\n", dis[n]);
return 0;
}
J. Stop Counting!(思维)
题意:一个长度为 n 的数组,选择某个前缀 或 某个后缀 或 某个前缀 + 某个后缀(不重合),问最大平均值
分析:
所以要么选前缀,要么选后缀,不会出现某前后缀同时选,取前缀平均值和后缀平均值的最大值即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int N = 1e6 + 7;
const int M = 2e6 + 7;
ll a[N], pre[N], las[N];
int main() {
int n;
double max1 = 0, max2 = 0;
scanf("%d", &n);
pre[0] = las[n + 1] = 0;
for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
for(int i = 1; i <= n; ++i) {
pre[i] = pre[i - 1] + a[i];
max1 = max(max1, 1.0 * pre[i] / i);
}
for(int i = n; i >= 1; --i) {
las[i] = las[i + 1] + a[i];
max2 = max(max2, 1.0 * las[i] / (n - i + 1));
}
printf("%.10f\n", max(max1, max2));
return 0;
}
标签:const,int,ll,tot,IH,edge,训练赛,第三场,dis 来源: https://blog.csdn.net/weixin_43871207/article/details/115095434