zoukankan      html  css  js  c++  java
  • hdu 4491 Windmill Animation

    A windmill animation works as follows:
    A two-dimensional set of points, no three of which lie on a line is chosen. Then one of the points is chosen (as the first pivot) and a line is drawn through the chosen point at some initial angle. The animation proceeds by rotating the line counter-clockwise about the pivot at a constant rate. When the line hits another of the points, that point becomes the new pivot point. In the two examples below, the points are (-1,1), (1,1), (0,0), (-1,-2) and (1,-2).

    Example 1


    In Example 1, the start point is point 1 and the line starts rotated 45 degrees from horizontal. When the line rotates to 90 degrees, point 4 is hit and becomes the new pivot. Then point 5 becomes the new pivot, then point 2 then point 1.

    Example 2


    In Example 2, the initial point is point 3 and the line starts horizontal. At 45 degrees, point 2 becomes the pivot, then at about 56 degrees, point 4 becomes the pivot. At about 63 degrees, point 3 becomes the pivot again, then point 5, point 1 and back to 3 as at the start.

    Write a program, which takes as input the points of the set, the initial point and the initial line angle and outputs the sequence of pivot points.
     
    Input
    The first line of input contains a single integer P, (1<= P <= 1000), which is the number of data sets that follow. Each data set should be processed identically and independently.

    Each data set consists of multiple lines of input. The first line of each data set consists of four space- separated decimal integers followed by a single floating-point value. The first integer is the data set number. The second integer is the number of points M to follow (3 <= M <= 20). The third integer gives the number, s , of the pivot points to output (3 <= s <= 20) and the fourth integer gives the index, I, of the initial point (1 <= I <= M). The floating-point value is the angle, A, in degrees, that the initial line is rotated counter-clockwise from horizontal (0 <= A < 180).

    The remaining M lines in the data set contain the coordinates of the set of points. Each line consists of an integer, the point.s index, I, and two floating-point values, the X and Y coordinates of the point respectively.
     
    Output
    For each data set there is a single line of output. It contains the data set number, followed by s space separated point indices (excluding the initial point index).
     
    Sample Input
    2 1 5 5 1 45 1 -1 1 2 1 1 3 0 0 4 -1 -2 5 1 -2 2 5 7 3 0 1 -1 1 2 1 1 3 0 0 4 -1 -2 5 1 -2
     
    Sample Output
    1 4 5 2 1 4 2 2 4 3 5 1 3 2
    题目分析:
    可谓说是一道简单模拟题,而且数据范围也很小。
    首先,对于每个点,与其他任何一点结对时,通过斜率求出轴正方向的夹角,范围应该是在0~pi,
    然后就是从给定初始点进行模拟呗,对于其他点(除之前传到它的那点),因为是逆时针旋转,所以
    对于两点角度mc[st][j]大于现在角度du的,角度之差为mc[st][j]-du,否则,将所得值加上pi,所有点
    中,得到最小差值的点即为下一个传递点,更新st pre(之前点) du 的值,这样循环s次就可以了
     
    # include<iostream>
    # include<cstring>
    # include<cstdio>
    # include<cmath>
    # define pi (4.0*atan(1.0))
    using namespace std;
    struct
    {
        double x,y;
    } a[25];
    double mc[25][25];
    int ca,m,s,st;
    double du;
    int ans[25];
    void creat()
    {
        int i,j;
        for (i=1;i<m;i++)
        for (j=i+1;j<=m;j++)
        {
            double angle;
            if (a[i].x==a[j].x)//横坐标相等的情况特判一下
            {
                mc[i][j]=pi/2;
                mc[j][i]=mc[i][j];
                continue;
            }
            angle=atan((a[i].y-a[j].y)/(a[i].x-a[j].x));
            if (angle<0) angle=angle+pi;
            mc[i][j]=angle;
            if (mc[i][j]==pi) mc[i][j]=0;
            mc[j][i]=mc[i][j];
        }
    }
    void solve()
    {
        int i,j,pre=st;
        du=du/180*pi;
        for (i=1;i<=s;i++)
        {
            double min=-1;
            int k=0;
            for (j=1;j<=m;j++)
            if (st!=j&&pre!=j)
            {
                double pp;
                pp=mc[st][j]-du;
                if (pp<0) pp=pp+pi;
                if (min==-1||min>pp)
                {
                    min=pp;
                    k=j;
                }
            }
            pre=st; //更新之前点pre的值
            du=mc[st][k]; //更新度数
            st=k;//更新当前点的值
            ans[i]=k;//记录每一步所到的点
        }
    }
    int main()
    {
        int p;
        scanf("%d",&p);
        while (p--)
        {
            int i;
            scanf("%d%d%d%d%lf",&ca,&m,&s,&st,&du);
            for (i=1;i<=m;i++) scanf("%d%lf%lf",&i,&a[i].x,&a[i].y);
            printf("%d ",ca);
            creat(); //构造任意两点角度的二维矩阵
            solve(); //模拟s次
            for (i=1;i<=s;i++)
            if (i<s) printf("%d ",ans[i]);
            else printf("%d
    ",ans[i]);
        }
        return 0;
    }
    /*
    该题反映的问题:
    1、# define pi 4.0*atan(1.0) 是将4.0*atan(1.0)整体替代pi的位置,
    所以应该将pi后面的全部打上括号
    2、低级错误,题目没看清楚,坐标的读入应该用实数
    */
    


  • 相关阅读:
    作业任务03
    作业任务02
    作业任务01
    Shell脚本编程01-shell编程与规范与变量
    Linux网络服务05-----DNS域名解析服务(二)
    Linux网络服务05-----DNS域名解析服务(一)
    Linux网络服务13----PXE 高效能批量网络装机
    网络基础知识
    Nginx 入门
    shell 脚本须知
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3255888.html
Copyright © 2011-2022 走看看