Codeforces Round #352 (Div. 2)

C. Recycling Bottles

题意:

在网格上有n个瓶子,现在有两个人A和B,他们有自己的起始位置,还有一个垃圾桶的位置,求捡完瓶子之后两个人走的最短距离是多少。捡瓶子的步骤是:先去捡瓶子,然后扔到垃圾桶。

思路:

我们先假设把所有的瓶子都捡了,记录一个答案 ans, 代表要走多少路,
然后我们找出来从 A 的出发点走会减少多少距离, 从 B 的出发点走会减少多少距离。
所以我们只需要找到两个距离的最大值就可以了。
加上一个特判。 当 n == 1 的时候,
首先可以肯定的是, 一定有一个人去捡瓶子,另外一个人减少的距离如果是正数,那么可以用 ans 减去,如果减少的距离是负数,那这个人就不用去捡瓶子了。

反思:

刚做这个题的时候,我想的是从 A 点出发,找一个离A 最近的瓶子,从 B 出发找一个离 B 最近的瓶子,然后发现样例都不能过。
然后苦思冥想才想着反过来做。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+100;
void dbg() {cout << endl;}
template<typename T, typename... A> void dbg(T a, A... x) {cout << a << ' '; dbg(x...);}
#define logs(x...) {cout << #x << " -> "; dbg(x);}
struct node{
	int id; 
	double val;
}a[N],b[N],t[N];
int x[N],y[N],ax,ay,bx,by,tx,ty,n;
double dis(int x, int y, int xx, int yy){
	return sqrt(1ll*(x-xx)*(x-xx) + 1ll*(y -yy)*(y-yy));
}
bool cmp(node A, node B){
	return A.val > B.val;
}
double ans;
int main(){
	scanf("%d%d%d%d%d%d",&ax,&ay,&bx,&by,&tx,&ty);
	scanf("%d",&n);
	for (int i = 0; i < n; ++i)
		scanf("%d%d",&x[i],&y[i]);
	for (int i = 0; i < n; ++i){
		t[i].id = i;
		t[i].val = dis(tx, ty, x[i],y[i]);
		ans += t[i].val * 2;
	}
	for (int i = 0; i < n; ++i){
		a[i].id = i;
		b[i].id = i;
		a[i].val = t[i].val - dis(ax,ay,x[i],y[i]);
		b[i].val = t[i].val - dis(bx,by,x[i],y[i]);
	}
 
	sort(a, a + n, cmp);
	sort(b, b + n, cmp);
	if (n == 1){
		if (a[0].val > b[0].val){
			ans -= a[0].val;
		} else{
			ans -= b[0].val;
		}
		printf("%.10lf\n",ans);
		return 0;
	}
 
	double tmp1, tmp2;
	if (a[0].id != b[0].id){
		tmp1 = a[0].val;
		if (b[0].val > 0) tmp1 += b[0].val;
		tmp2 = b[0].val;
		if (a[0].val > 0) tmp2 += a[0].val;
 
	}else{
		tmp1 = a[0].val;
		if (b[1].val > 0) tmp1 += b[1].val;
		tmp2 = b[0].val;
		if (a[1].val > 0) tmp2 += a[1].val;
	}
	if (tmp1 < tmp2) swap(tmp2, tmp1);
	ans -= tmp1;
	printf("%.10lf\n",ans);
	return 0;
}

D. Robin Hood

题意:

有一些人,每个人都有一些金币,现在要求每次最富的人给最穷的人一个金币,直到 k天,问最富和最穷的金币差,最终的金币差是一定的。

思路:

我们可以看到,这个题的金币数量是很多的,但是他的人数并不多,所以我们从人数入手,解决这个问题。
首先把每个人的金币数量排个序, 从小到大排序,
然后从小到大增加 k 个金币, 看看最穷的人有多少金币 mx,
然后从大到小减少 k 个金币, 看看最富的人有多少金币 mn。

如果 mn > mx 那么答案就是 mn - mx。
否则答案 不是 0 就是 1, 这个用 sum % n 的结果来判断。 ‘

需要注意的是 mn mx 的初始话, 以及 mx mn 的更新。

反思:

刚开始做这个题的时候,没有想法, 后来发现这个题就是把最大的移到最小的上面去。以前好像做过这样的题。
刚开始的时候,我还想着二分, 二分最富的人最终会剩下多少钱。然后不了了之。

这样好像就是个套路题, 从小到大排序,然后从小到大,一点一点增加金币。

That’s all

#include<bits/stdc++.h>
using namespace std;
const int N = 5e5+100;
int a[N],n,m,k,c[N];
long long sum,mx,mn;
void dbg() {cout << endl;}
template<typename T, typename... A> void dbg(T a, A... x) {cout << a << ' '; dbg(x...);}
#define logs(x...) {cout << #x << " -> "; dbg(x);}
int main(){
	scanf("%d%d",&n,&k);
	for (int i = 1; i <= n; ++i){
		scanf("%d",&c[i]);
		sum += c[i];
	}
	sort(c+1, c + n + 1);
	mx = c[1];
	mn = c[n];
	long long tmp = 0;
	for (int i = 1; i < n; ++i){
		if (tmp + 1ll*i * (c[i+1] - c[i])  <= k){
			tmp += 1ll* i * (c[i+1] - c[i]);
		} else{
			tmp = k - tmp;
			mx = c[i] + (tmp / i);	
			break;
		}
		mx = c[i+1];
	}
	tmp = 0;
	for (int i = n - 1; i >= 1; --i){
		if (tmp + 1ll * (n - i) * (c[i+1] - c[i]) <= k){
			tmp += 1ll * (n - i) * (c[i+1] - c[i]);
		} else{
			tmp = k - tmp;
			mn = c[i+1] - (tmp / (n - i));
			break;
		}
		mn = c[i];
	}
	if (mn > mx){
		printf("%lld\n",mn - mx); 
	} else {
		if (sum % n) puts("1"); else puts("0");
	}
	return 0;
}

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值