Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目信息
农夫约翰有 nn 片连续的农田,编号依次为 1∼n。
其中有 kk 片农田中装有洒水器。
装有洒水器的农田的编号从小到大依次为 x1,x2,…,xkx1,x2,…,xk。
在某个炎热的中午,约翰觉得是时候给他的所有农田浇水了。
每个洒水器在打开以后,向两侧方向洒水,并且随着开启时间延长,有效覆盖距离也不断增长。
具体来说,我们将第 xi片农田中的洒水器打开,经过 11 秒后,第 xixi 片农田被其覆盖,经过 22 秒后,第 xi−1,xi+1 片农田被其覆盖,经过 j 秒后,第 xi−(j−1),xi+(j−1) 片农田被其覆盖。
注意,每个洒水器的有效覆盖距离在每经过整数秒后,才会有所增长。
例如,经过 2.52.5 秒后,被第 xi片农田中的洒水器覆盖的农田仍是第 xi−1,xi+1 片农田,而不是第 xi−1.5,xi+1.5 片农田。
现在,约翰将所有洒水器同时打开,请问经过多少秒后,所有农田均被灌溉。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含两个整数 n,k。
第二行包含 k 个整数 x1,x2,…,xkx1,x2,…,xk。
输出格式
每组数据输出一行答案。
数据范围
前三个测试点满足 1≤n≤5, 所有测试点满足 1≤T≤200,1≤n≤200,1≤k≤n,1≤xi≤n,xi−1<xi,T 组数据的 n 相加之和不超过 200。
输入样例:
3
5 1
3
3 3
1 2 3
4 1
1
输出样例:
3
1
4
思路
当我们看到这道题的时候可以发现这是一道跟生活中息息相关的题目,我们可以采用模拟的思路去解决这个问题。把每一个洒水器都放进数组,然后计住他们的下标,把下标值标为1,当浇水开始时,他们脚下的土地就已经浇水过了。然后我们就开始循环直到count被浇灌的土地值为目标值,每一次循环都遍历数组,然后判断1的土地,其(i - 1)和(i + 1)就是下一次会被浇灌的土地,然后记录他们的下标入栈,当循环结束后,挨个出栈,然后根据下标把他们的值变为1,代表该土地被浇灌。每一次出栈更新后,浇水的时间加1。
代码
#include <iostream>
#include <cstring>
#include <stack>
using namespace std;
const int N = 201;
int q[N];
bool bb[N];
int main()
{
int n;
cin >> n;
int time;
stack<int> a;
int count, jj;
while(n --)
{
int m, z;
cin >> m >> z;
memset(q, 0, sizeof q);
memset(bb, false, sizeof bb);
for(int j = 0;j < z; j++)
{
int a;
cin >> a;
q[a] = 1;
}
count = 0;
time = 0;
//cout << "m=" << m << endl;
while(count != m)
{
int t = 0, w =0;
for(int i = 1;i <= m;i ++)
{
if(q[i] == 1){
if(!bb[i]) count ++;
bb[i] = true;
//count ++;
//cout << count << endl;
if(i - 1 >= 1 && q[i - 1] == 0) t = i -1;
if(i + 1 <= m && q[i + 1] == 0) w = i + 1;
a.push(t);
a.push(w);
}
//count ++;
}
while(!a.empty()){
jj = a.top();
q[jj] = 1;
a.pop();
}
//q[t] = 1, q[w] = 1;
time ++;
}
cout << time << endl;
}
}