LOJ 1307 Counting Triangles

题目大意:

        现有N根长度各异的木棍(3 ≤ N ≤ 2000),问共可以组成多少个不同的三角形。

        现有多个测例(测例数会告诉你),每个测例中给定N以及N根木棍的长度(每根木棍长度范围为[1, 10^9]),对于每个测例都打印出可以组成的三角形的总数量。

题目链接

注释代码:

/*                                       
 * Problem ID : LOJ 1307 Counting Triangles 
 * Author     : Lirx.t.Una                                       
 * Language   : C++                      
 * CPU        : 1.384                                       
 * Memory     : 1696                                       
*/

#include <algorithm>
#include <iostream>
#include <cstdio>

//maximum number of sticks
//木棍的最大数量
#define MAXSTICKN       2001

using namespace std;

int     a[MAXSTICKN];//存储每根木棍的数量

int
main() {
	
    int     nscn, iscn;
    int     n;//木棍数量
    int     i, j;//计数变量
    int     lft, rht;//临时区间界限
	
    int     ans;
	
    scanf("%d", &nscn);
    iscn = 0;
	
    while ( nscn-- ) {
		
        scanf("%d", &n);
		
        for ( i = 0; i < n; i++ )
            scanf("%d", a + i);
		
        sort(a, a + n);//排序后以便二分查找
		
		//从左往右扫描,先确定两根木棍i、j
		//再根据三角形规则确定后面的第三根
        for ( ans = 0, i = 0; i < n - 2; i++ )
            for ( j = i + 1; j < n - 1; j++ ) {
				
                lft = a[j] - a[i] + 1;//第三边一定大于前两遍之差(+1表示大于)
                rht = a[i] + a[j] - 1;//第三遍一定小于前两遍之和(-1表示小于)
				
                lft = lower_bound(a, a + n, lft) - a;//二分找出大于等于lft的第一个元素在数组中的位置
                rht = upper_bound(a + lft, a + n, rht) - a - 1;//二分找出大于rht的第一个元素在数组中的位置
				
				//两个重要的剪枝,如果lft和rht都在j前面表示之前已经计算过了,可不用重复计算
                if ( lft <= j )
                    lft = j + 1;
				
                if ( rht <= j )//rht小于等于j就表示无第三根可以组成三角形的木棍了,因为可行区间在[lft, rht]上
                    continue;
				
                if ( lft <= rht )//如果lft大于rht也表示这样的三角形不存在了
                    ans += rht - lft + 1;
            }
			
			printf("Case %d: %d\n", ++iscn, ans);
    }
	
    return 0;
}

无注释代码:

#include <algorithm>
#include <iostream>
#include <cstdio>

#define MAXSTICKN       2001

using namespace std;

int     a[MAXSTICKN];

int
main() {
	
    int     nscn, iscn;
    int     n;
    int     i, j;
    int     lft, rht;
	
    int     ans;
	
    scanf("%d", &nscn);
    iscn = 0;
	
    while ( nscn-- ) {
		
        scanf("%d", &n);
		
        for ( i = 0; i < n; i++ )
            scanf("%d", a + i);
		
        sort(a, a + n);
		
        for ( ans = 0, i = 0; i < n - 2; i++ )
            for ( j = i + 1; j < n - 1; j++ ) {
				
                lft = a[j] - a[i] + 1;
                rht = a[i] + a[j] - 1;
				
                lft = lower_bound(a, a + n, lft) - a;
                rht = upper_bound(a + lft, a + n, rht) - a - 1;
				
                if ( lft <= j )
                    lft = j + 1;
				
                if ( rht <= j )
                    continue;
				
                if ( lft <= rht )
                    ans += rht - lft + 1;
            }
			
			printf("Case %d: %d\n", ++iscn, ans);
    }
	
    return 0;
}

单词解释:

triangle:n, 三角,三角形

stick:n, 木棍

valid:adj, 有效的,合法的,正当的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值