题目描述
输入描述
输出描述
输入样例
3
1 1 1 1
2 2 2 2
3 3 3 3
输出样例
62
样例说明
题目大意:时间从 t = 0 开始,每秒可以抢救任意一个坐标为( x , y , z + t * v )的宝物并花费 x ² + y ² + z ² + t ² v ² + 2 t v z 的力量,求抢救完所有的宝物需要花费的最小力量。
本题吃了没学过图论的亏, 比赛时用 pair 数对存入 z 的变化量后排序暴力枚举,虽然愉快的通过了样例但提交通过率 0%(泪目)。
正确做法是最小匹配权,通过暴力找增广路直至不能最优,其中权值为深度变化量即
△ = t ² v ² + 2 t v z ,而对于每组输入的( x , y , z ),可以先 sum + = x ² + y ² + z ² 进行初始化。
参考代码
#include<bits/stdc++.h>
using namespace std;
int n;
struct node{
long long z,v;
int po;
}c[305];
long long f(long long t ,node one){
return t*t*one.v*one.v+2*one.v*t*one.z;
}
void g(int p){
int t;
for(int i=0;i<n;++i)
if(c[i].po==p){
t=i;
break;
}
for(int i=0;i<n;++i)
if(f(i,c[i])+f(t,c[t])>f(t,c[i])+f(i,c[t])){
swap(c[i],c[t]);
g(c[t].po);
g(p);
}
}
int main (){
cin>>n;
int a,b,z,v;
long long ans=0;
for(int i=0;i<n;++i){
c[i].po=i;
cin>>a>>b>>z>>v;
ans+=(a*a+b*b+z*z);
c[i]={z,v,i};
}
for(int i=0;i<n;++i)
g(i);
for(int i=1;i<n;++i)
ans+=f(i,c[i]);
cout<<ans<<endl;
return 0;
}