UVA 12123 Magnetic Train Tracks

The rail roads of Japan are being redesigned. So the governent is planning to install ultra-modern Magnetic trains instead of the current normal trains. As fuel price have gone high and nations have shut down their nuclear plants so the price of electricity/battery is also sky high. To reduce power consumption the Japanese government is trying to descourage people from riding trains – as a result the ticket price is also kept sky high and it is strictly proportional to the square of the distance between two stations.

 

All the trains move in clockwise or counter clockwise order in a closed triangular track. These triangular tracks can be formed by connecting any three stations in clockwise or counterclockwise order. For simplicity you can assume that a station is denoted by a point in a two dimensional Cartesian Coordinate system. But these triangular tracks and ticket pricing policy can create new troubles. As the ticket price between two stations is proportional to the square of the distance, people often avoid the shortest route to destination and rather choose the longer one through another station. This causes more electricity expense per passenger and creates unwanted crowd in the stations. So the government would prefer not to make such tracks.

 

Figure 1: The figure above shows 6 places. It also shows all possible triangular tracks (not necessarily valid site) by connecting them. The green track is one invalid track site, on the other hand the red track is one valid track site. There are five other valid track sites in the above figure. fv

For example in the figure on the left you can see a closed triangular track marked with green. If someone wants to go from station D to station E he can go directly by riding a clockwise train or can go via station C by riding a counter clockwise train: That is he first buys ticket from station D to C and then he buys ticket of station C to E. But in the current ticket pricing system the route via C (which is also much longer) will be cheaper. So this site CED is not a place to build a track. For the similar reasons AEB is a valid site for building track. On a valid track the shortest distance between any two stations is also the unique cheapest route between them. Given the coordinate of all stations you will have to find the number of sites (a group of three places) for valid tracks.

 

Input

The input file contains at most 15 sets of inputs. The description of each set is given below:

 

Each set starts with an n (2<n<1201) which denotes the number of stations. Each of the next n lines contains two integer xi, yi (0≤xi, yi≤10000) which denotes the Cartesian coordinate of the i-th station. You can assume that a track can be built via through any three stations, no three places will be collinear to avoid the problem of degenerate tracks and the connecting railroad between two stations can always be represented by the straight line connecting them.

 

Output
For each set of input produce two line of output. The first line contains the serial of output and the second line displays the total number of sites where a track can be built. Look at the output for sample input for details.

 

Sample Input            Output for Sample Input

6
26 23
51 94
103 110
164 107
116 67
73 16
2
1 1
2 2
0

Scenario 1:

There are 6 sites for making valid tracks

Scenario 2:

There are 0 sites for making valid tracks

 



思路:题目相当于求有多少个锐角三角形。 其实,我们只需要求出有多少个钝角三角形就行了。我们可以固定一个点,然后这个点是钝角的点,其他的点只需要按极角排序就能很简单的进行统计了。


代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cstring>
#include <stdio.h>
#include <cmath>
#include <math.h>
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define rrep(i,b,a) for(int i = (b); i >= (a); --i)
#define clr(a,x) memset(a,(x),sizeof(a))
#define LL long long
#define eps 1e-10
using namespace std;
const int maxn = 1500 + 5;
const double PI = 4.0 * atan(1.0);
int n;

int dcmp(double a,double b)
{
    if (a < b - eps) return -1;
    else if (a > b + eps) return 1;
    return 0;
}

struct Point
{
    int x,y;
    double ang;
    Point(int x=0,int y=0)
    :x(x),y(y) {
        ang = atan2(y,x);
    }
    bool operator < (const Point & pt) const
    {
        return ang < pt.ang;
    }
}pt[maxn],p[maxn];

void input()
{
    rep(i,0,n) scanf("%d%d",&pt[i].x,&pt[i].y);
}

LL Dun(int x,int y)
{
    rep(i,0,n) p[i] = pt[i];
    int c = 0;
    rep(i,0,n) if (pt[i].x != x || pt[i].y != y) {
        pt[c] = pt[i];
        pt[c].x -= x; pt[c].y -= y;
        pt[c].ang = atan2(pt[c].y,pt[c].x);
        ++c;
    }
    sort(pt,pt+c);
    LL ans = 0;
    int j = 0,k = 0;
    rep(i,0,c) {
        if (j <= i) j = i + 1;
        while (j < c && dcmp(pt[j].ang,pt[i].ang + PI * 0.5) < 0) ++j; --j;
        if (k <= j) k = j + 1;
        while (k < c && dcmp(pt[k].ang,pt[i].ang + PI * 1.5) <= 0) ++k; --k;
        ans += (k-j);
    }
    rep(i,0,n) pt[i] = p[i];
    return ans;
}

void solve()
{
    LL ans = n * (n-1) * (n-2) / 6;
    rep(i,0,n)
        ans -= Dun(pt[i].x,pt[i].y);
    printf("There are %lld sites for making valid tracks\n",ans);
}

int main()
{
    #ifdef ACM
        freopen("in.txt", "r", stdin);
       // freopen("out.txt","w",stdout);
    #endif // ACM
    int cas = 0;
    while (scanf("%d",&n),n) {
        input();
        ++cas;
        printf("Scenario %d:\n",cas);
        solve();
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值