给你N根不同长度的木棍;您必须使用木棍形成一些三角形。如果三角形的面积为正,则三角形有效。你的任务是找出使用木棍形成有效三角形的方法的数量。
输入
输入以整数T (≤ 10)开头,表示测试用例的数量。
每个案例都以包含整数N (3 ≤ N ≤ 2000)的行开头。下一行包含N个整数,表示木棍的长度。您可以假设长度不同并且每个长度都在[1, 10 9 ]范围内。
输出
对于每个案例,打印案例编号和可以形成有效三角形的方式总数。
Sample
Inputcopy | Outputcopy |
---|---|
3 5 3 12 5 4 9 6 1 2 3 4 5 6 4 100 211 212 121 | Case 1: 3 Case 2: 7 Case 3: 4 |
思路:
设二小边为i,j(i<j)
1.首先要搞懂什么是有效三角形:两边之和大于第三边,也即满足最小的两边加和大于第三边即可
2.我们不妨将木棍的长度升序排序,利用二分查找函数lower_bound找到目标区间第一个大于等于二者之和的数字,这个时候有两种可能:
(1)这个数字和j相等,也即此时没有有效的三角形,因为棍子的数组按照升序排序,也说明此后都会有任何有效三角形,我们直接break掉循环就可以了
(2)这个数字不等于j,那么这个数字再减去该数组得到的就是所有小于二者之和的数字的个数,此时,i,j也同样在这个个数内,且i,j不断的向右移动,此时要想获得小于二者之和的数字的个数就要再减去j+1;
3.最后将这些个数加和再输出ans,这题就算是完成了
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int m, n, p = 1, ans, sum = 0;
cin >> m;
while (m--)
{
n = 0;
ans = 0;
cin >> n;
ll a[2005] = { 0 };
for (int i = 0; i < n; i++)
cin >> a[i];
sort(a, a + n);
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
sum = a[i] + a[j];
int sum1 = lower_bound(a + j, a + n, sum) - a;
if (sum1 == j)
break;
ans +=sum1-j-1;
}
}
printf("Case %d: %d\n", p++, ans);
}
}