• HDU3952 Fruit Ninja 暴力扫


      http://acm.hdu.edu.cn/showproblem.php?pid=3952

      这是一道计算几何的题目,刚好昨晚看了一下基本的计算几何,而这题就是叉积的应用。

      设有两个共起点向量  A,B, 其中 A = { x1, y1 },   B = { x2, y2 };    A  X  B = x1 * y2 + x2 * y1;

      如果 A X B > 0, 那么说明A向量在B向量的顺时针方向,反之则说明A在B的逆时针方向。等于零,说明两个向量重合。

      那么对于某一点,就可以运用这一点来判定该点是在线段的左还是右了,即选择一个端点,再连接这个端点和所求的一点,构造出另一个向量......

      这题是给定了N个水果的各个端点,那么我们可以断定这个穿过最多的水果的直线如果不全由端点构成的话,一定会有无数条,因为稍微的旋转和平移这条直线一定还是满足最多的水果的。因此,该题就转化为枚举所有的两点确定的一条之直线,然后计算哪条直线穿过的水果数最多。

      代码如下:

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    using namespace std;
    
    struct fruit
    {
    	int num;
    	int p[12][2];
    }f[12];
    
    int point[105][2];
    
    int dir( int p1, int p2, int x0, int y0 ) // 计算叉积
    {
    	return ( x0 - point[p1][0] ) * ( point[p2][1] - point[p1][1] ) + ( y0 - point[p1][1] ) * ( point[p2][0] - point[p1][0] );
    }
    
    
    
    bool attack( int p1, int p2, int No )
    {
    	for( int i = 0; i < f[No].num; ++i )
    	{
    		for( int j = i + 1; j < f[No].num; ++j )
    		{
    			if( dir( p1, p2, f[No].p[i][0], f[No].p[i][1] ) * dir( p1, p2, f[No].p[j][0], f[No].p[j][1] ) <= 0 )
    				return true;
    		}// 由于是凸多边形才可以这样做
    	}	
    	return false;
    }
    
    int cal( int p1, int p2, int N )
    {
    	int ans = 0;
    	for( int i = 0; i < N; ++i )
    	{
    		if( attack( p1, p2, i ) )
    			ans++;
    	}
    	return ans;
    }
    
    int main(  )
    {
    	int T;
    	scanf( "%d", &T );
    	for( int t = 1; t <= T;\
    		   	++t )
    	{
    		int N, sum = 0, max = 0;
    		scanf( "%d", &N );
    		for( int i = 0, j = 0; i < N; ++i )
    		{
    			int K;
    			scanf( "%d", &K );
    			f[i].num = K;
    			sum += K;
    			for( int t = 0; t < K; ++j, ++t )
    			{
    				scanf( "%d %d", &point[j][0], &point[j][1] );
    				f[i].p[t][0] = point[j][0];
    				f[i].p[t][1] = point[j][1];
    			}		
    		}
    		for( int i = 0; i < sum; ++i )
    		{
    			for( int j = i + 1; j < sum; ++j )
    			{
    				int temp = cal( i, j, N );
    				max = max > temp ? max : temp; 
    			}
    		}
    		printf( "Case %d: %d\n", t, max );
    	}
    }
    

      

  • 相关阅读:
    redhat,centos Linux常用命令LS之常用功能
    人生信用卡
    如何让Redhat Linux启动时进入字符终端模式(不进入XWindow)
    OpenJDK和JDK区别
    Linux rpm 命令参数使用详解[介绍和应用]
    linux 的vim命令详解
    centos6.4安装javajdk1.8
    samba服务器 实现Linux与windows 文件共享
    SELinux 宽容模式(permissive) 强制模式(enforcing) 关闭(disabled) 几种模式之间的转换
    linux学习之 Linux下的Eclipse安装
  • 原文地址:https://www.cnblogs.com/Lyush/p/2233490.html
Copyright © 2020-2023  润新知