第一次写博客,不当处请多多指教。
一. 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题没想到暴力。