组合三角形
【题目描述】:
桌面上凌乱地摆放着N个木棍,长度分别为{a1,a2…,ai,…an},N<=6000,1<=ai<=100,000,000,选择三个木棍为边组成三角形,问有多少种不同的组合。三个木棍的不同排列,只能算一种组合。假设ai<=ajak。
【输入描述】:
第一行,一个整数N。
第二行N个木棍的长度。
【输出描述】:
只有一个数表示能够组成三角形的组数,最后的结果可能比较大。
【样例输入】
7
3 5 7 4 9 5 1
【样例输出】
15
【数据范围及描述】:
难得遇到这种简单点的题目了, 虽然简单我还是要写博客的-。-
n=6000,n三次暴力肯定是不行滴,所以先排个序咯,看看有什么规律
样例 1 3 4 5 5 7 9
我们发现排完序后只要【a[i]+a[j]>a[k]】 (0<i<j<k<n+1)就满足形成三角形。
所以我们穷举i和j,k从j+1开始: while(a[i]+a[j]>a[k]&&k<=n) k++;
如果存在一个k恰好使得不满足上述条件了,那么说明前面的都满足,所以加上j-i-1个解。
当j在增加的时候,无需每个j都修改k,k的值可以在原来的基础上增加,因为i是不变的,j往后推,k也必须往后推
如果存在一个k恰好使得不满足上述条件了,那么说明前面的都满足,所以加上j-i-1个解。
当j在增加的时候,无需每个j都修改k,k的值可以在原来的基础上增加,因为i是不变的,j往后推,k也必须往后推
这样就解决问题了
中心程序:
for(int i=1;i<=n-2;i++)
{ int k=i+2;
for(int j=i+1;j<=n-1;j++)
{
while(a[i]+a[j]>a[k]&&k<=n)
k++;
ans+=k-j-1;
}
全部代码如下
for(int i=1;i<=n-2;i++)
{ int k=i+2;
for(int j=i+1;j<=n-1;j++)
{
while(a[i]+a[j]>a[k]&&k<=n)
k++;
ans+=k-j-1;
}
全部代码如下
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define ll long long
int n,a[6005];
ll ans;
using namespace std;
int main()
{ cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);
for(int i=1;i<=n-2;i++)
{ int k=i+2;
for(int j=i+1;j<=n-1;j++)
{
while(a[i]+a[j]>a[k]&&k<=n)
k++;
ans+=k-j-1;
}
}
cout<<ans<<endl;
//while(1);
return 0;
}