
题目大意:在n个数中所有相邻的两个数差的绝对值如果不大于d,成这n个数为光滑的,否则如果能更换n个数中一个数使其变成光滑的成为半光滑的。现在给你n个数,如果这n个数为光滑的或半光滑的输出Y,否则输出N。
其中光滑的容易判断,再判断出半光滑的,其余都是不光滑的
不光滑的有两种情况:
- 一共有两段光滑的数组组成,在两段的交界处存在断点(就是不光滑的地方)。如n=6,d=5 ; 数组为3 7 10 4 5 6。在10 和 4之间就是一个断点。
- 有三段光滑的数组,但是中间的只有一个数。如n=7,d = 5;数组为3 7 9 30 1 2 3。在30这个点处出现断点。
断点是否能修改的判断
找到断点后我们还需要判断该断点是否能修改,1情况中有两种修改可能,修改10位置或者修改4位置。在2情况中只能自改30位置,该位置能否修改只需要判断该位置前后的差的绝对值是否不大于2d。
所以我们只需要遍历一遍数组,寻找断点,当断点小于等于1,且点断能修改输出Y,否则输出N
#include <iostream>
using namespace std;
int main()
{
int n, d;
int a[1010];
while (cin >> n && n)
{
cin >> d;
for (int i = 0; i < n; i++)//输入数据
{
cin >> a[i];
}
int cnt = 0;//计数修改次数
int flag = 1;//标记是否光滑
for (int i = 0; i < n - 1; i++)
{
if (cnt > 1)//如果修改过两次
{
flag = 0;
break;
}
if (abs(a[i] - a[i + 1]) > d)//出现断点
{
if (abs(a[i + 1] - a[i + 2]) > d)
//这就是上面断点的第二种情况
{
cnt++;//标记已经修改过一次
if (abs(a[i] - a[i + 2]) > 2 * d)
//这种情况只有30的位置能修改,所以只需要判断一次
{
flag = 0;
break;
}
i++;//这里需要跳过一次,9后面是30,这里有断点,30能修改,修改有30位置就是光滑的,不需要在判断,而且如果在判断30位置就需要对30重新赋值
}
else
{
if (abs(a[i] - a[i + 2]) > 2 * d)//能否修改a[i+1]
{
if (i - 1 < 0)//这里最好判断a[i]前面是否还有数
{
flag = 0;
break;
}
else if (abs(a[i - 1] - a[i + 1]) > 2 * d)//能否修改a[i]
{
flag = 0;
break;
}
}
}
}
}
if (flag)
{
cout << "Y\n";
}
else
{
cout << "N\n";
}
}
}
本文详细解析了如何判断一组数是否构成光滑数列或半光滑数列,通过遍历数列并判断相邻数差值,识别断点并验证其可调整性,最终确定数列属性。
3161

被折叠的 条评论
为什么被折叠?



