A - Birthday Cake VJ(计算几何 平面欧拉)

57 篇文章 0 订阅
33 篇文章 0 订阅

A - Birthday Cake
On his birthday, John’s parents made him a huge birthday cake! Everyone had a wonderful dinner, and now it’s time to eat the cake. There are nn candles on the cake. John wants to divide the cake into nn pieces so that each piece has exactly one candle on it, and there are no left-over pieces. For that, he made mm cuts across the cake. Could you help check if John’s cuts successfully divide the candles on the cake?

Formally, the cake is a circle of radius rr centered at (0,0)(0,0). The candles are nn distinct points located strictly inside the circle. Each cut is a straight line ax+by+c=0ax+by+c=0, described by three coefficients aa, bb, and cc.

Input

Input starts with three integers nn (1≤n≤501≤n≤50), mm (1≤m≤151≤m≤15), and rr (1≤r≤1001≤r≤100) on the first line.

The next nn lines give the locations of the candles. Each line has two integers xx and yy giving the coordinates of one candle (0≤x2+y2−−−−−−√<r0≤x2+y2<r).

The next mm lines give the coefficients of the cutting lines. Each line has three integers aa, bb, and cc (0≤|a|,|b|≤100,0≤|c|≤200000≤|a|,|b|≤100,0≤|c|≤20000) describing a line of the form ax+by+c=0ax+by+c=0. The values aa and bb are not both zero.

All candles and lines are distinct. No candle is on a cut line. No line is completely outside or tangent to the cake. The input guarantees that the number of cake pieces remains the same if any cut line is shifted by at most 10−410−4 in any direction. The input also guarantees that each candle remains in the interior of the same piece of cake if its position is shifted by at most 10−410−4 in any direction.

Output

Output “yes” if John’s cuts successfully divide the cake so that each piece he obtains has exactly one candle on it. Otherwise, output “no”.

Sample Input 1 Sample Output 1
4 2 3
0 1
1 0
-1 0
0 -1
-1 1 0
2 1 0
yes
Sample Input 2 Sample Output 2
4 3 3
0 1
1 2
-1 2
0 -1
-1 1 -2
-1 -1 2
0 -1 0
no
Sample Input 3 Sample Output 3
3 2 3
2 1
0 0
-1 -2
1 1 -2
3 6 12
yes
Sample Input 4 Sample Output 4
3 1 2
0 0
-1 1
1 -1
-2 2 1
no

前置技能 : 平面欧拉公式
于是有一个平面的欧拉公式(最后我没想起来)

V-E+F = 2

V是点数,E是边数,F是面数(也就是这里的块数),考虑在圆形中,所以

V-E+F=1

易知F = n

V是园内交点数,易知对于每一条直线来说,如果有k个交点,会被分成k+1条边
学习了几个新的函数来简化程序。(后面补充)

PS 因为近期学的计算机底层的东西多一些然后想到了几个逻辑运算符号来解决输出的问题
心路历程: 一开始感觉是数学方面的,然后感觉应该能做, 2 发 WA, 2 发 RE, 感觉还是能做,然后一血。。。。。。。。。。。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 10005;
int a[maxn];
int b[maxn];
int c[maxn];
bool vis[maxn][maxn];
pair<int,int> d[maxn];
int n,m,r;
int main()
{
    for(int i = 0; i < maxn; i++)
        for(int j = 0; j < maxn; j++)
            vis[i][j] = 1;
    scanf("%d %d %d",&n,&m,&r);
    for(int i = 0; i<n; i++)
        scanf("%d%d",&d[i].first,&d[i].second);
    for(int i = 0; i<m; i++)
    {
        bool t[maxn] = {0};
        scanf("%d %d %d",&a[i],&b[i],&c[i]);
        for(int j=0; j<n; j++)
            if(a[i]*d[j].first + b[i]*d[j].second + c[i]<0)t[j] = 1;
        for(int j = 0; j < n; j++)
            if(t[j])
                for(int k = 0; k < n; k++)
                    if(!t[k])
                    {
                        vis[k][j] = 0;
                        vis[j][k] = vis[k][j];
                    }
    }
    for(int i=0; i<n; i++)
    {
        int cnt = 0;
        for(int j=0; j<n; j++)
            if(vis[i][j])cnt++;
        if(cnt>1)
           return 0&printf("no\n");
    }
    int v = 0,e = 0;
    for(int i = 0; i < m; i++)
    {
        int cnt = 0;
        for(int j = 0; j < m; j++)
            if(i!=j)
            {
                if(a[i]*b[j] == a[j]*b[i])
                    continue;
                double y = -1.0*(a[j] * c[i] - a[i] * c[j])/(a[j] * b[i] - a[i] * b[j]);
                double x = 1.0*(b[i] * c[j] - b[j] * c[i])/(a[i] * b[j] - a[j] * b[i]);
                if(x * x + y * y < r * r)
                    cnt++;
            }
        v += cnt;
        e += cnt + 1;
    }
    v /= 2;
    if(v - e + n != 1)
      return 0&printf("no\n");

    printf("yes\n");
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值