CH Round #48 - Streaming #3 (NOIP模拟赛Day1)8.9总结)

 

一、数三角形

什么叫三角形?这个应该是每个人都知道的。在本题中,我们不允许三角形出现退化的情况,即每条边的长度与每个角的大小也应大于0

现在平面上有n个两两不重合的点,第i个点的坐标为(x[i],y[i])。你需要计算,以它们作为顶点,一共能构成的三角形的个数。注意,即使是两个全等的三角形,只要它们的位置是不同的,就认为是不同的三角形,详见样例。

暴力:看了一下n只有100,直接枚举3个顶点,用叉积或三角形三边关系(a+b>c(a<=b<=c))进行判断,n^3

给力点:可选取一个点为原点,进行极角排序,然后用同一角度的点与其他角度的用乘法原理匹配方案,为了避免180°三点共线如图:

CH Round #48 - Streaming #3 (NOIP模拟赛Day1)8.9总结)_第1张图片

可先将三、四象限的点旋转180°,再进行排序。

排序可用点x、y相对于z叉积大于0时,点x在y的逆时针方向,但这样会死循环(没确立起始点,角度大于180°时叉积为负,会分不清前后),由于作了以上旋转操作,没有大于180°的角,有不循环的前后之分,故不会出错。附代码:

#include

 

02

#include

 

03

#include

 

04

#include


 

05

#include

 

06

#include


 

07

#include

 

08

#include

 

09

#include

 

10

#include


 

11

#include

 

12

#include

 

13

#include

 

14

using namespace std;

 

15

int n,i,j,k,ans,tot;

 

16

double x[110],y[110],s;

 

17

int main()

 

18

{


 

19

    cin>>n;

 

20

    for(i=1;i<=n;i++)

 

21

    {


 

22

        cin>>x[i]>>y[i];

 

23

    }

 

24

    for(i=1;i<=n;i++)


 

25

    for(j=i+1;j<=n;j++)

 

26

    for(k=j+1;k<=n;k++)

 

27

    {

 

28

        /*double xx=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));

 

29

        double yy=sqrt((x[i]-x[k])*(x[i]-x[k])+(y[i]-y[k])*(y[i]-y[k]));

 

30

        double zz=sqrt((x[j]-x[k])*(x[j]-x[k])+(y[j]-y[k])*(y[j]-y[k]));

 

31

        if (xx+yy>zz&&xx+zz>yy&&yy+zz>xx)

 

32

        {

 

33

            if (not(x[i]==x[j]&&x[j]==x[k])&¬(y[i]==y[j]&&y[j]==y[k]))

 

34

            {*/

 

35

                if ((x[i]-x[j])*(y[j]-y[k])!=(x[j]-x[k])*(y[i]-y[j]))ans++;

 

36

            /*}

 

37

        }*/

 

38

    }

 

39

    cout<

 

40

}

 

 

二、4和7

萌萌哒doge突然想吃药了!

现在有一排格子,从左向右标号为0mdoge最初在0号格子中。

一共有n堆药,第i堆药有a[i]粒,被放在b[i]格子里。

每次,萌萌哒doge可以跳到它右边4格或右边7格的位置。求它最多能吃到的药的个数。注意,doge不必跳到格子m,而是可以随时结束游戏。

做题时不知为何想不到,其实枚举一下就可发现规律:(任何题目,先打暴力,不仅可以对拍,还可以找规律,王道……)

可以调到的距离有:4、7、8、11、12、15、16、18、19、20……

可以发现,在距离大于17时都可以用4和7匹配到,此时我们是在第i个位置,用前i-1个位置的方案求解,取max时,只需将距离小于17的位置取max,大于17的,我们可以先存储一个数组s[i]表示,1~i+1的方案中的最大值,o(1)求出,取max,避免一个个枚举o(n)会超时,然后由于题目说可以随时结束游戏,那么就要用ans在更新时随时记录方案的最大值,最后输出。

三、反射镜

注:坐标平面没有边缘,光线不会因为碰到边界而中途停下,m的意义是所有镜子坐标绝对值的最大值不会超过m

从前有一个坐标网格(其中坐标的绝对值不会超过m)。从左到右x坐标逐渐增加,而从下到上y坐标逐渐增加。

在网格中摆放着n面镜子,第i面镜子的坐标为(x[i],y[i])。镜子均与坐标轴成45°角。所以共有两种类型的镜子:“\”型和“/”型。特殊地,原点处不会有任何镜子,也不会有某个位置有多面镜子。

镜子的两个面都能够反射光线,而中间不透光,例如,对于一个“/”型镜子,从下面射入的光线会被反射到右方向,而从左面射入的光线会被反射到上方向。

现有一条光线从原点所在格子沿x轴正方向射出,求它走过$T$格路程后所在的位置。

由数据范围入手,假设我们用普通的模拟(即一面镜子一面镜子的走下去,直到走完路程为止),那么在不出现循环的情况下,要走n次,n<=100000,故可以做。而当出现循环时,易证得循环只可能从起点时出现,如图:CH Round #48 - Streaming #3 (NOIP模拟赛Day1)8.9总结)_第2张图片

这时就是最后15分的差别了,最后数据将路程调至最大,然后以较小距离摆放镜子,循环走下去——超时,这时我们可以记录一下走到每个镜子面(即要分方向)的时间点,然后用当前时间点与其求差,得出循环的时间,求mod,就省去多次循环模拟的时间。

接着就得解决寻找当前镜子的后继,可以分别按横坐标、纵坐标排序,二分得出,当然,我们试验发现,每次二分找到的都是当前镜子在数组中的位置+1或-1,那么我们可以记下每面镜子在排序后两个数组中的位置,O(1)得出,起点除外,要二分,或者把它也加进去排序,再记下在数组中的位置。

依上所述,时间复杂度为nlogn+logn或o(n)+logn

你可能感兴趣的:(信息学)