HDU-2108-Shape of HDU(Java+向量叉乘的简单应用)

HDU 同时被 2 个专栏收录
78 篇文章 0 订阅
193 篇文章 0 订阅

Shape of HDU

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5575    Accepted Submission(s): 2531


Problem Description
话说上回讲到海东集团推选老总的事情,最终的结果是XHD以微弱优势当选,从此以后,“徐队”的称呼逐渐被“徐总”所取代,海东集团(HDU)也算是名副其实了。
创业是需要地盘的,HDU向钱江肉丝高新技术开发区申请一块用地,很快得到了批复,据说这是因为他们公司研发的“海东牌”老鼠药科技含量很高,预期将占全球一半以上的市场。政府划拨的这块用地是一个多边形,为了描述它,我们用逆时针方向的顶点序列来表示,我们很想了解这块地的基本情况,现在请你编程判断HDU的用地是凸多边形还是凹多边形呢?
 

Input
输入包含多组测试数据,每组数据占2行,首先一行是一个整数n,表示多边形顶点的个数,然后一行是2×n个整数,表示逆时针顺序的n个顶点的坐标(xi,yi),n为0的时候结束输入。
 

Output
对于每个测试实例,如果地块的形状为凸多边形,请输出“convex”,否则输出”concave”,每个实例的输出占一行。
 

Sample Input
  
4 0 0 1 0 1 1 0 1 0
 

Sample Output
  
convex 海东集团终于顺利成立了!后面的路,他们会顺顺利利吗? 欲知后事如何,且听下回分解——
 

Author
lcy
 

Source
 

Recommend
lcy   |   We have carefully selected several similar problems for you:   1086  1392  1115  2111  2110 


遇到这种题,要一步一步思考来,切忌操之过急!
首先我们要明确凸多边形的定义是:所谓凸多边形,就是把一个多边形任意一边向两方无限延长成为一条直线,如果多边形的其他各边均在此直线的同旁,那么这个多边形就叫做凸多边形。

这时如果按照一般的数学思路来想,我第一个想到的思路是,任选多边形两顶点,写出这两点的直线方程,在将除那两点之外的所有点都带进未知数x,y进行计算,看所有结果是否同号(正负号),如果同号则其他顶点都在该直线的同侧,为凸多边形,如果异号则为凹多边形.
这个思路没有错,但是实现起来太繁琐了,感兴趣的童鞋可以自己试试!但是我们也可以想想有没有更加好的方法呢?

解题思路: 叉乘的运用
原理是在平面上去(0,0)来分割多边形为多个三角形,然后用叉乘来求三角形的面积(有向)再求和。这样的话可以把凸N多边形转化为N-2个三角形,然后求解N个三角形即可,输入定点的顺序,无论逆时针还是顺时针都行!


/*
 * 向量点积:两个向量的点积为标量,A向量*B向量=A*B*cosa;
 * 向量叉积:两个向量的叉积是向量,它们的绝对值相当于两个向量构成平行四边形的面积,A向量*B向量=A*B*sina;
 * 相当于三角形的2倍,然后我们可以利用三角形的面积的正负来判断是否是凸边形.因为如果是凹边形,a>90度小于180度,
 * sina<0,得出的结果一定为负数!
 */

import java.awt.Point;
import java.io.*;
import java.util.*;

public class Main
{
	public static class Spot
	{
		int x, y;
	}

	public static int CrossProduct(int x1, int x2, int y1, int y2)
	{
		return x1 * y2 - x2 * y1;
	}

	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
		Scanner input = new Scanner(System.in);
		while (input.hasNext())
		{
			int n = input.nextInt();
			int ans = 0;
			if (n == 0)
				break;
			Spot a[] = new Spot[n + 2];
			for (int i = 0; i < n; i++)
			{
				a[i] = new Spot();
				a[i].x = input.nextInt();
				a[i].y = input.nextInt();
			}
			a[n] = a[0];
			a[n + 1] = a[1];
			for (int i = 2; i <= n + 1; i++)
			{
				int x1 = a[i - 1].x - a[i - 2].x;
				int y1 = a[i - 1].y - a[i - 2].y;
				int x2 = a[i].x - a[i - 1].x;
				int y2 = a[i].y - a[i - 1].y;
				ans = CrossProduct(x1, x2, y1, y2);
				if (ans < 0)
					break;
			}
			if (ans < 0)
				System.out.println("concave");
			else
			{
				System.out.println("convex");
			}
		}
	}

}


 

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值