HDU3952 Fruit Ninja (几何)

15 篇文章 0 订阅

这题是让你求一条线能够穿过最多的水果(碰到一个点也算)。

可以证明,枚举两个点组成的线是可行的。

因为假设有一条线穿过N个水果,那么把它平移一些使得还是穿过N个但是已经不能再平移了,这样的话,这条线肯定是在某个水果的某个端点上。

再以这个端点,旋转这条线,还是穿过N个,直到不能旋转为止(再旋转可能就不能穿过N个了),这样的话,肯定还是这条线碰到了另外一个端点。

所以只要枚举两个端点即可。

只有一个水果的话,特判下。

#include<map>
#include<set>
#include<queue>
#include<stack>
#include<math.h>
#include<time.h>
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<limits.h>
#include<string.h>
#include<string>
#include<algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
using namespace std;
const int MAX = 35;
struct point {int x,y;};
struct polygon {point p[MAX]; int n; } ;
polygon g[MAX];
int crossProduct(point a,point b,point c){
    return (c.x-a.x)*(b.y-a.y) - (b.x-a.x)*(c.y-a.y);
}
bool s21_inst(point s1,point s2,point l1,point l2)
{
    return crossProduct(l1,l2,s1)*crossProduct(l1,l2,s2) <= 0;
}
int solve(point a,point b,int n){
    int ans=0;
    for(int i=0;i<n;i++){
        int len=g[i].n;
        g[i].p[len] = g[i].p[0];
        for(int k=0;k<len;k++)
            if( s21_inst(g[i].p[k],g[i].p[k+1],a,b) )
            {
                ans++;
                break;
            }
    }
    return ans;
}
int main()
{
    int ncases,n;
    int ind=1;
    scanf("%d",&ncases);
    while(ncases--){
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%d",&g[i].n);
            for(int k=0;k<g[i].n;k++)
                scanf("%d%d",&g[i].p[k].x,&g[i].p[k].y);
        }
        if(n==1){
            printf("Case %d: 1\n",ind++);
            continue;
        }
        int mmax=0;
        for(int i=0;i<n;i++)
            for(int k=0;k<g[i].n;k++)
                for(int j=i+1;j<n;j++)
                    for(int l=0;l<g[j].n;l++){
                        int ans=solve(g[i].p[k],g[j].p[l],n);
                        if(ans > mmax) mmax = ans;
                    }
        printf("Case %d: %d\n",ind++,mmax);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值