A题(贪心)
由题意得,要让斜边长度之和最小,就要让每次打磨产生的贡献最大,共建可以理解为打磨前后的长度差,通过结构体排序这个长度差还有相应的直角边(结构体部分参考大佬的),由于w比较小,直接循环暴力,用优先队列进行维护,要注意可能存在w用不完的情况,所以需要将y小到不能打磨的情况单独计算并
#include <bits/stdc++.h>
using namespace std;
double m(double x,double y){
return sqrt(x*x+y*y)-sqrt(x*x+(y-1)*(y-1));
}
struct vbr{
double z,x,y;
bool operator<(const vbr other) const{
return z < other.z;
}
};
int main(){
int n,w;cin>>n>>w;
double ans=0;
priority_queue<vbr> p;
for(int i=1;i<=n;i++){
double x,y;
cin>>x>>y;
vbr M1={m(x,y),x,y};
if(y<1){
ans+=sqrt(x*x+y*y);
continue;
}
p.push(M1);
}
while(w--&&!p.empty()){
vbr M2=p.top();
p.pop();
if(M2.y<1){
ans+=sqrt(M2.x*M2.x+M2.y*M2.y);
w++;
continue;
}
vbr M3={m(M2.x,M2.y-1),M2.x,M2.y-1};
p.push(M3);
}
while(!p.empty()){
vbr M=p.top();
p.pop();
ans+=sqrt(M.x*M.x+M.y*M.y);
}
cout<<fixed<<setprecision(6)<<ans;
}
进行出队
using namespace std;
double m(double x,double y){
return sqrt(x*x+y*y)-sqrt(x*x+(y-1)*(y-1));
}
struct vbr{
double z,x,y;
bool operator<(const vbr other) const{
return z < other.z;
}
};
int main(){
int n,w;cin>>n>>w;
double ans=0;
priority_queue<vbr> p;
for(int i=1;i<=n;i++){
double x,y;
cin>>x>>y;
vbr M1={m(x,y),x,y};
if(y<1){
ans+=sqrt(x*x+y*y);
continue;
}
p.push(M1);
}
while(w--&&!p.empty()){
vbr M2=p.top();
p.pop();
if(M2.y<1){
ans+=sqrt(M2.x*M2.x+M2.y*M2.y);
w++;
continue;
}
vbr M3={m(M2.x,M2.y-1),M2.x,M2.y-1};
p.push(M3);
}
while(!p.empty()){
vbr M=p.top();
p.pop();
ans+=sqrt(M.x*M.x+M.y*M.y);
}
cout<<fixed<<setprecision(6)<<ans;
}
进行出队

京公网安备 11010502036488号