hdu 3952 Fruit Ninja

今天阿里巴巴比赛的第二题。我和党对博弈还有概率一窍不通,结果做了两题后就搞不动了 = =。。

这题计算几何水题哈,这个游戏我在我姐的手机上还玩过,蛮好玩的。

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

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

因为假设有一条线穿过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 )
#define BUG puts("here!!!")
#define STOP system("pause")

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)//向量 ac 在 ab 的方向 顺时针是正 
{
	return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);
}
bool s2l_inst(point s1,point s2,point l1,point l2)//s是线段,l是直线 
{	// xyd包括端点在直线上。xy是穿过 
	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( s2l_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: ",ind++);
			printf("1\n");
			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: ",ind++);
		printf("%d\n",mmax);
	}

return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值