传送门
题意
你的坐标是 ( 0 , 0 , 0 ) (0,0,0) (0,0,0),有 m m m个宝物,分别坐标是是 ( x i , y i , z i ) (x_{i},y_{i},z_{i)} (xi,yi,zi),它的 z z z坐标以每秒下沉 v i v_i vi深度,你每次获取一个宝物的费用是两者的距离的平方,每秒只能获取一个宝物,从第 0 0 0秒开始,问获取所有宝物的最小费用
分析
题目就是转化成每分钟都要选一颗宝石,然后求最小的费用
这个题卡掉了最小费用流,可以用
b
f
s
bfs
bfs版的
K
M
KM
KM求解,复杂度为
O
(
n
3
)
O(n ^ 3)
O(n3)
代码
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
#define _CRT_SECURE_NO_WARNINGS
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef vector<int> VI;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int N = 310;
const ll mod = 1000000007;
const double eps = 1e-6;
const double PI = acos(-1);
template<typename T>inline void read(T &a) {
char c = getchar(); T x = 0, f = 1; while (!isdigit(c)) {if (c == '-')f = -1; c = getchar();}
while (isdigit(c)) {x = (x << 1) + (x << 3) + c - '0'; c = getchar();} a = f * x;
}
ll w[N][N];
ll la[N], lb[N];
bool va[N], vb[N];
int match[N];
int n;
ll delta, upd[N];
ll p[N];
ll c[N];
int x[N], y[N], z[N], v[N];
void bfs(int x)
{
int a, y = 0, y1 = 0;
for (int i = 1; i <= n; ++ i)
p[i] = 0, c[i] = INF;
match[y] = x;
do {
a = match[y], delta = INF, vb[y] = true;
for (int b = 1; b <= n; ++ b) {
if (!vb[b]) {
if (c[b] > la[a] + lb[b] - w[a][b])
c[b] = la[a] + lb[b] - w[a][b], p[b] = y;
if (c[b] < delta) //还是取最小的
delta = c[b], y1 = b;
}
}
for (int b = 0; b <= n; ++ b)
if (vb[b])
la[match[b]] -= delta, lb[b] += delta;
else c[b] -= delta;
y = y1;
} while (match[y]);
while (y)match[y] = match[p[y]], y = p[y];
}
ll KM()
{
for (int i = 1; i <= n; ++ i)
match[i] = la[i] = lb[i] = 0;
for (int i = 1; i <= n; ++ i) {
for (int j = 1; j <= n; ++ j)
vb[j] = false;
bfs(i);
}
ll res = 0;
for (int y = 1; y <= n; ++ y) //若匹配失败w[match[y]][y]=INF;
res += w[match[y]][y];
return res;
}
ll dis(int x, int y, int z) {
return 1ll * x * x + 1ll * y * y + 1ll * z * z;
}
int main() {
read(n);
for (int i = 1; i <= n; i++) read(x[i]), read(y[i]), read(z[i]), read(v[i]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
w[i][j] = -1ll * dis(x[j], y[j], z[j] + (i - 1) * v[j]);
dl(-1ll * KM());
return 0;
}
本文介绍了一种解决三维空间中随时间变化的宝物收集问题的算法,通过最小费用流的方法实现,利用KMKM算法求解每秒选择一个宝物以获得最小总费用的问题。
238

被折叠的 条评论
为什么被折叠?



