A. Direction Change
题意:给出一个矩阵,要求从左上角走到右下角,每次可以向上下左右四个方向移动一个单位,但是不能连续朝一个方向走两次。问最少的步数,如果不能走到则输出-1。
思路:模拟一下发现只有两种方式可以走,判断奇偶性即可。
AC code:
#include <bits/stdc++.h>
using namespace std;
int n,m;
int main()
{
int t;
cin>>t;
while(t--){
cin>>n>>m;
if(n>m) swap(n,m);
if(n==1){
if(m>2) cout<<-1<<endl;
else cout<<m-1<<endl;
continue;
}
long long ans=(n-1)*2;
if((m-n)&1) ans+=2*(m-n)-1;
else ans+=2*(m-n);
cout<<ans<<endl;
}
return 0;
}
B. Social Distance
题意:m个椅子组成一个环,编号0-m-1,有n个人要坐,每个人有个要求就是自己的左边和右边a[i]个椅子都不能坐人。问所有人是否都坐得下。
思路:当n>m时,一定不能全部坐下。要使所有人都坐下的最优策略就是让每把空椅子尽量满足多个人的要求,我们可以对这n个数降序排序,然后从大到小遍历,依次让他们入座,第一个数空出来的椅子数一定大于等于第二个人的,因此第二个人可以把第一个人空出来的椅子数也利用起来满足自己的要求。然后求出每个人依次坐的位置与(m-1)判断即可。每个人坐的位置是上一个人的范围右边界的下一个位置。
AC code:
#include <bits/stdc++.h>
using namespace std;
int n,m,a[100010];
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
if(n>m){
cout<<"NO"<<endl;
return ;
}
sort(a+1,a+n+1,greater<int>());
if(a[1]>m){
cout<<"NO"<<endl;
return ;
}
long long sum=2*a[1];
for(int i=2;i<=n;i++){
sum++;
if(sum>(m-1)){
cout<<"NO"<<endl;
return ;
}
sum+=a[i];
}
cout<<"YES"<<endl;
}
int main(){
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
我最开始写的与m比较,哭死。
C. Make it Increasing
题意:给你一个乱序数组a和一个全部是0的数组b,可以进行两类操作,选择下标i,让b[i]+a[i]或者b[i]-a[i]。求最小的操作次数使得数组b成严格的升序。
思路:贪心的话可以发现数组b里不管如何贪都一定有个0,即不需要操作,从而使得操作数最小,然后n<=5000,因此可以暴力遍历0所在的位置,然后求出当前0所在位置让b数组成严格升序的操作数,取最小即可。
AC code:
#include <bits/stdc++.h>
using namespace std;
int n,a[5010];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
long long res=1e17;
for(int i=1;i<=n;i++){
long long pre=0ll;
long long ans=0ll;
for(int j=i-1;j>=1;j--){
if(-a[j]<pre){
ans++;
pre=-a[j];
}else{
ans+=(((-pre)/a[j])+1);
pre=-a[j]*((-pre)/a[j]+1);
}
}
pre=0ll;
for(int j=i+1;j<=n;j++){
if(a[j]>pre){
ans++;
pre=a[j];
}else{
ans+=(pre/a[j]+1);
pre=a[j]*(pre/a[j]+1);
}
}
// cout<<i<<' '<<ans<<endl;
res=min(ans,res);
}
printf("%lld",res);
return 0;
}