Recycling Bottles
题意:
两个人收废品,一个人一次只能拿一件废品到回收站,然后再出来拿下一个废品。问两个人一共走的距离最少是多少
思路:
因为每次只能拿一个并且后面都是从回收站出来,所以影响距离的就是如何选择第一个废品点。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int ax,ay,bx,by,tx,ty;
int n;
struct Bin{
double dist;
double disa;
double disb;
int id;
}bin[100005];
bool cmp1(const Bin &a,const Bin &b){
return a.dist - a.disa > b.dist - b.disa;
}
bool cmp2(const Bin &a,const Bin &b){
return a.dist - a.disb > b.dist - b.disb;
}
int main()
{
// freopen("data.txt","r",stdin);
scanf("%d%d%d%d%d%d",&ax,&ay,&bx,&by,&tx,&ty);
scanf("%d",&n);
double sum = 0;
for(int i = 0; i < n ; ++i){
int x,y;
scanf("%d%d",&x,&y);
bin[i].dist = sqrt((x-tx)*1LL*(x-tx)+(y-ty)*1LL*(y-ty));
bin[i].disa = sqrt((x-ax)*1LL*(x-ax)+(y-ay)*1LL*(y-ay));
bin[i].disb = sqrt((x-bx)*1LL*(x-bx)+(y-by)*1LL*(y-by));
sum += bin[i].dist;
bin[i].id = i;
}
sum *= 2;
sort(bin,bin+n,cmp1);
double mina = bin[0].dist - bin[0].disa;
int ida = bin[0].id;
double minaa = bin[1].dist - bin[1].disa;
sort(bin,bin+n,cmp2);
double minb = bin[0].dist - bin[0].disb;
int idb = bin[0].id;
double minbb = bin[1].dist - bin[1].disb;
if(ida == idb){
double m = max(minaa+minb,minbb+mina);
m = max(m,mina);m = max(m,minb);
sum -= m;
} else {
if(mina > 0 && minb >0)sum = sum-mina-minb;
else sum -= max(mina,minb);
}
printf("%.6lf\n",sum);
}
Robin Hood
题意:
一个城市中有一大群人,Robin Hood每次将最富有的一个人的金币拿给最贫穷的一个人。如果财富值相同就随机选取一个。经过k次以后,这个城市最富的跟最穷的金币差是多少
以下翻译官网题解:
我们可以将操作分开进行,先进行所有的增加操作,再进行所有的减少操作。使用下面的算法:
我们要将数组中最小的数加一,这个操作进行k次。可以二分k次操作后的最小值。来看看怎么样确定最小值是大于还是等于p。如果
假设最小值是m,找出m以后我们要把所有比m小的加到m。但是可能有些操作暂时还未进行,未进行的操作数最大是n-1,要不然我们就可以把所有等于m的数加一,这样最小值就不是m了。由于最小的那些数应当相同,我们可以只把等于m的一些数增加。
减操作可以用同样的算法。最后我们打印出最终数组中的
我的代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
int n,k;
int c[500005];
int main()
{
// freopen("data.txt","r",stdin);
scanf("%d%d",&n,&k);
ll sum = 0;
for(int i = 0; i < n; ++i){
scanf("%d",&c[i]);
sum += c[i];
}
sort(c,c+n);
ll avgl = sum/n;
ll avgr = sum/n + (sum%n ? 1 : 0);
ll l = c[0];ll r = avgl;
while(l <= r){
ll mid = (l+r) >> 1;int tot = k;
int i;
for(i = 0; c[i] < mid ; ++i){
tot -= (mid - c[i]);
if(tot < 0)break;
}
if(tot < 0)r = mid - 1;
else l = mid + 1;
if(tot > 0 && tot <= i-1 ){r = mid;break;}
}
int mina = r;
l = avgr;r = c[n-1];
while(l <= r){
ll mid = (l+r) >> 1;int tot = k;
int i;
for(i = n-1; c[i] > mid ;--i){
tot -= (c[i] - mid);
if(tot < 0) break;
}
if(tot < 0)l = mid + 1;
// else if(tot == 0){l = r = mid;break;}
else r = mid - 1;
if(tot > 0 && tot <= n-i-2 ){l = mid;break;}
}
int minb = l;
printf("%d\n",minb - mina);
return 0;
}