Codeforces Round #783 (Div. 2)ABC题解

第一次写博客,不当处请多多指教。


一. A Direction Change

题目链接
题意:给定n行,m列的矩形,从矩形左上角(1,1)运动到矩形右下角(n,m)最少进行几步?每次运动可以向上,下,左,右一步,但每两次运动方向不能相同。
题解:我们选取(n,m)中的较小值min,较大值max,(1,1)-(min,min),步数为(min-1)*2,接下来可证:从(min,min)-(n,m),如果(max-min)为偶数,步数为(max-min)*2,如果(max-min)为奇数,步数为(max-min)*2+1.
code如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
int t;
int main() {
	cin >> t;
	while(t--) {
		ll n,m;
		cin >> n >> m;
		int p = 0;//用于标志n,m谁大谁小
		ll xx = min(n,m);//n,m中小的值
		if(n < m) p = 0;
		else p = 1;
		ll ans = 0;
		ll x = 1;
		ll y = 1;
		int flag = 0;
		if(n == 1 && m > 2) flag = 1;//特判
		if(n > 2 && m == 1) flag = 1;
		if(flag == 0) {
			ans += (xx - 1) * 2;//x,y必能到xx点,计算步数
			x = xx;//更新坐标
			y = xx;
			if(p == 0) {
				if((m - xx) % 2 == 0) ans += (m - xx) * 2;//规律
				else ans += (m - xx) * 2 - 1;
			}
			if(p == 1) {
				if((n - xx) % 2 == 0) ans += (n - xx) * 2;//规律
				else ans += (n - xx) * 2 - 1;
			}
		}

		if(flag == 0) cout << ans << endl;
		else cout << -1 << endl;
	}
}

二. B Social Distance

题目链接
题意:给定人数n,座位数m,接下来给定n个人两边各需要空多少位置a[i],请你判断n个人能否坐下?
题解:对a[i]进行从大到小排序,然后从i=1,开始遍历,每个人自身需要一个位置,然后我们只需判断i的一边是否有满足的空座位就行了(因为,我们把i放到了i-1空座位的下一个位置,这一边的a[i]<a[i-1],无需判断).
code如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int t;
bool cmp(int a,int b) {
	return a > b;
}
int main() {
	cin >> t;
	while (t--) {
		ll n, m;
		ll a[100006];
		cin >> n >> m;
		int flag = 0;
		for (int i = 0; i < n; i++) {
			cin >> a[i];
		}
		sort(a, a + n, cmp);//按占座人数从大到小排序
		ll ans = a[0] * 2 + 1;//第一个大的人所占位置
		ll s = m - ans;//第一个人之后所剩位置
		if (s == 0 && n > 1) {//如果座位没了并且后续还要有人坐
			flag = 1;
		}
		if (s < 0) {//座位没了,第一个人需要的座位数就不够
			flag = 1;
		}

		if (!flag) {

			for (int i = 1; i < n; i++) {

				if (s < 1) {//当前剩余的座位给一个人坐都不够
					flag = 1;
					break;
				}
			
				if (s >= 1) {//减去自己坐的位置
					s = s - 1;
				}
				if (s > a[i]) {//剩余座位比i所占一边座位大时
					s = s - a[i];
				} else {
					s = 0;
				}
			}
		}
		if (flag == 1) {
			cout << "NO" << endl;
		} else {
			cout << "YES" << endl;
		}
	}
}

三. C Make it Increasing

题目链接
题意:给定长度n的a数组,初始值为0的b数组每次可进行如下操作:b[i]-a[i],
b[i]+a[i].问:把b变成一个递增的数列,最少需要几步?
题解:关键的是找到b数组中数值为0的位置,我们可以采取暴力法,从i遍历到n-1,依次按题意找出递增数列需要的步数,求其中最小的就可以了.
code如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f3f3f3f3f3f;
int main() {
	ll n;
	cin >> n;
	ll a[5200];
	ll b[5200];
	ll ans = 1e18;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	for (int i = 0; i < n; i++) {
		memset(b, 0, sizeof(b));
		for (int j = i + 1; j < n; j++) {
			ll d = b[j - 1] / a[j];
			d++;
			b[j] = a[j] * d;
		}
		for (int j = i - 1; j >= 0; j--) {
			ll d = b[j + 1] / a[j];
			d++;
			b[j] = a[j] * d;
		}
		ll cnt = 0;
		for (int j = 0; j < n; j++) {
			cnt += (b[j] / a[j]);
		}
		ans = min(ans, cnt);
	}
	cout << ans << endl;
}

四. 总结

比赛时a题找规律找慢了,c题没想到暴力。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值