AcWing 2031. 折叠绳子(枚举)

【题目描述】
农夫约翰有一条长度为 L L L的绳子,可用于农场周围的各种任务。
绳子在不同的位置有 N N N个绳结,包括两个端点处各有一个。
约翰注意到,在某些位置,他可以将绳子对折,这样,相对的绳索上的绳结就可以彼此完全对齐:

在这里插入图片描述

请帮助约翰统计具有此属性的折叠点数。
允许在某个绳结处折叠,但不允许在端点绳结处折叠。
折叠后,较长的一侧可以有多余节点。

【输入格式】
第一行包含两个整数 N N N L L L
接下来 N N N行,每行包含一个 0 ∼ L 0\sim L 0L范围内的整数,表示一个绳结的位置。其中两行包含的数字分别是 0 0 0 L L L

【输出格式】
输出有效折叠位置的数量。

【数据范围】
1 ≤ L ≤ 10000 1≤L≤10000 1L10000
1 ≤ N ≤ 100 1≤N≤100 1N100

【输入样例】

5 10
0
10
6
2
4

【输出样例】

4

【样例解释】
有效折叠位置为 1 , 2 , 3 , 8 1,2,3,8 1,2,3,8

【分析】


首先,除了两个端点绳结以外其它每个绳结均可能作为对折点,此外每两个相邻的绳结的中点也可能作为对折点,因为若要在两个相邻的绳结中选择对折点,除中点外其它任何位置均无法满足这两个相邻点对折后完全重合。

因此我们枚举以上两种情况的所有可能的对折点(最多大概只有 2 N 2N 2N个点),再判断该点是否满足要求即可。由于取中点时涉及浮点数运算,为避免精度问题可以看成其它点到两个相邻点的距离是否相等,或者将所有点的坐标乘二这样中点坐标就为整数了。


【代码】

#include 
#include 
#include 
using namespace std;

const int N = 110;
int a[N];
int n, l, res;

bool check(int l, int r)
{
    for (int i = l, j = r; i >= 0 && j < n; i--, j++)
        if (a[l] - a[i] != a[j] - a[r]) return false;
    return true;
}

int main()
{
    cin >> n >> l;
    for (int i = 0; i < n; i++) cin >> a[i];
    sort(a, a + n);
    for (int i = 1; i < n - 1; i++)//枚举除了两端点外的所有结点
        if (check(i, i)) res++;
    for (int i = 1; i < n; i++)//枚举每组相邻两结点的中点
        if (check(i - 1, i)) res++;
    cout << res << endl;
    return 0;
}

你可能感兴趣的:(AcWing习题,算法,c++)