第 1 题:旋转
思路:转换行列直接输出
#include<bits/stdc++.h>
using namespace std;
const int N=300;
int f[N][N];
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>f[i][j];
}
}
// 从列开始
for(int i=0;i<m;i++)
{
for(int j=n-1;j>=0;j--)
{
cout<<f[j][i]<<" ";
}
cout<<endl;
}
}
第 2 题:附近最小
思路:滑动窗口,当前范围内的最小值可以依赖前一个范围的最小值来进行更新
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1000010;
ll f[N],n,k;
ll idx=0,min1=0x3f3f3f3f;
void check(ll l,ll r) {
min1=f[l];
idx=l;
for(ll i=l; i<=r; i++) {
if(f[i]<=min1) { //取最后面的最小值,方便更新
min1=f[i];
idx=i;
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1; i<=n; i++) {
cin>>f[i];
}
cin>>k;
for(int i=1;i<=n;i++)
{
ll l=i-k>=1?i-k:1;
ll r=i+k<=n?i+k:n;
if(l<=idx)//包含在原先最小值的范围内
{
if(f[r]<=min1)//最新加入进来的是否小于最小值
{
min1=f[r];//更新
idx=r;
}
cout<<min1<<" ";
}
else{
check(l,r);//重新更新范围内的最小值
cout<<min1<<" ";
}
}
}
第 3 题:扫地机器人
思路:贪心,但是卡了第4和第9个样例QAQ

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
ll f[N];//存放机器人位置
ll v[N];//存放对应机器人分配的格子
ll k,n;
bool vis[N];
void solve(int l,int r) {
ll t=f[r]-f[l]-1;//两个机器人之间的格子数
ll tt=abs(v[r]-v[l]);//判断相邻两个机器人间谁的格子数多
if(t>tt) {
t-=tt;
v[l]=v[r]=max(v[l],v[r]);//如果足够分配的话,保持两边一致
} else {
t-=t;
v[l]>v[r]?v[r]+=t:v[l]+=t;//如果不够分配的话,使两边的差距尽可能的小
}
if(t) {
v[l]+=t/2;
v[r]+=t/2;
if(t%2) {
v[r]++;
}
}
}
int main() {
cin>>n>>k;
ll len;
for(int i=0; i<k; i++) cin>>f[i];
sort(f,f+k);
if(k==1)cout<<2*(n-1)<<endl;
else {
//初始化起始端和末端
f[0]-1>=0?v[0]=f[0]-1:v[0]=0;
v[k-1]=n-f[k-1];
for(int i=0;i<k-1;i++) {
solve(i,i+1);
}
sort(v,v+k);
cout<<v[k-1]*2<<endl;
}
}
/*
解题思路:
本题为一道比较明显的二分题目。
题目要求最少花费时间。由于每个机器人的工作时间可能不同,那么这些机器人各自的花费时间中的最大值(设为 t )的就是本题要求的答案,
需要做的是使得 t 最小。将最大花费时间(t)最小化,显然需要使用二分求解。
假设某个机器人需要清扫 a,b,c,d 四个格子,因为这个机器人清扫完还需要回到最初始的位置,所以无论这个机器人初始位置在什么地方,
其清扫路径的本质都是重复两次 a 到 b,b 到 c,c 到 d 的过程,花费时间为 6,由此,假设某个机器人清扫的格子范围为 l,
那么这个机器人花费的时间为 (l-1)\times*2。所以只需要对机器人清扫的范围(l)进行二分即可,最后的答案为 t=(l-1)\times*2。
显然当每个机器人清扫的范围大小相同时,花费时间最小。
可以对清扫范围进行二分,然后验证其答案的正确性即可,判断条件是清扫范围可以使得每个格子都能够扫到
可以明显的知道,最左边的格子由左边第一台机器人清扫,花费时间是最少的,在此可以采用贪心的思想,
让每台机器人都要优先清扫其左边还未扫的到格子,然后再往右扫,在二分得到的范围下往右扫得越多越好,
这样可以减少右边下一个机器人需要往左扫的范围,增加其往右扫的范围,以此类推,可减少清扫时间。
综上,本题采用二分加贪心的思想解答。
*/
#include<bits/stdc++.h>
using namespace std;
int robot[1000005];//机器人位置
int n, k;
bool check(int len)
{
int sweep = 0;//sweep代表清扫到了哪个位置
for(int i = 1; i <= k; i++)
{
if(robot[i] - len <= sweep)//如果当前机器人只扫左侧,能够覆盖左侧未清扫的位置,则可进行当前机器人的清扫
{
if(robot[i] <= sweep)//如果当前机器人已经处于清扫过的位置,则当前机器人只扫右侧区域
sweep = robot[i] + len - 1;
else//否则从上一个清扫到的位置继续
sweep += len;
}
else//当前机器人只扫左侧,不能覆盖左侧未清扫的位置,当前方案不可行,返回
return 0;
//cout<<sweep<<endl;
}
return sweep>=n; //表示当前方案可行
}
int main()
{
cin >> n >> k;
for(int i = 1; i <= k; i++)
{
cin >> robot[i];
}
sort(robot + 1, robot + k + 1);//首先对机器人的位置进行排序
int L=0, R=n, M, ans;
while(L <= R)//二分清扫范围
{
M = (L + R) / 2;
if(check(M))//如果当前方案可行,则缩小清扫范围,试图寻找更小的方案
{
R = M - 1;
ans = M;
}
else//如果方案不可行,则扩大清扫范围,寻找可行方案
L = M + 1;
}
cout << (ans - 1) * 2 << endl;//计算并输出答案
return 0;
}