Fruit Ninja

Fruit Ninja

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 3
描述
Fruit Ninja is a popular classic game. During the game, fruits will up to the air, and your aim is cut as more fruits as possible with a line.
Fruit Ninja_第1张图片
Even if the line touch a point of a fruit, the fruit also be cut.
输入
The first line is a number T(1<=T<=30), represents the number of case. The next T blocks follow each indicates a case.
The first line of each case contains one integer N (1<=N<=10)
Then N lines follow, each line contains a integer K(3<=K<=10), represent the number points of the fruit, then K*2 integers follow, each two integers represent one point of the fruit.(with anticlockwise order)
I promise all fruits are convex polygon, and any two fruit have no common point.
输出
For each case, output the number of case and the maximum fruits you could cut with a line.(as shown in the sample output)
样例输入
2
3
3 0 0 1 0 1 1
3 1 2 2 1 2 2
3 3 1 3 0 4 0
3
4 0 0 1 0 1 1 0 1
4 2 0 3 0 3 1 2 1
4 0 99 1 99 1 100 0 100
样例输出
Case 1: 3

Case 2: 2

思路:计算几何, 暴力求解, 遍历所有两两fruit上的点找直线与所有水果相交最多。

//nyoj 402

#include <stdio.h>

#define MAX_SIZE 31

typedef struct Node
{
    int x, y;
}Pos;

typedef struct ITEM
{
    Pos pt[MAX_SIZE];
    int n;
}Item;

Item fruit[101];

int iscolinear(Pos a, Pos b, Pos c)        //判断ab, cb向量的位置
{
    return (a.x-b.x)*(c.y-b.y)-(a.y-b.y)*(c.x-b.x);
}

int isintersect(Pos a1, Pos a2, Pos b1, Pos b2)  //判断a1a2, b1b2两条直线是否相交
{
    return iscolinear(a1, a2, b1)*iscolinear(a1, a2, b2) <= 0;
}

int getNum(Pos a, Pos b, int n)           //遍历所有fruit, 获取与ab相交的个数
{
    int num = 0, m;
    for(int i = 0; i < n; i++)
    {
        m = fruit[i].n;
        fruit[i].pt[m] = fruit[i].pt[0];
        for(int j = 0; j < m; j++)
        {
            if(isintersect(a, b, fruit[i].pt[j], fruit[i].pt[j+1]))
            {
                num++;
                break;
            }
        }
    }
    return num;
}

int main()
{
    int t, n, m, i, j, ti, tj, ans, temp, cnt = 0;
    scanf("%d", &t);
    while(t--)
    {
        ans = 0;
        scanf("%d", &n);
        for(i = 0; i < n; i++)
        {
            scanf("%d", &m);
            fruit[i].n = m;
            for(j = 0; j < m; j++)
            {
                scanf("%d%d", &fruit[i].pt[j].x, &fruit[i].pt[j].y);
            }
        }
        if(n == 1)
        {
            printf("Case %d: 1\n", ++cnt);
            continue;
        }
        for(i = 0; i < n; i++)           //遍历所有两两fruit上的点的连线用getNum()获取直线穿过水果的个数并更新ans
        {
            for(j = i+1; j < n; j++)
            {
                for(ti = 0; ti < fruit[i].n; ti++)
                {
                    for(tj = 0; tj < fruit[j].n; tj++)
                    {
                        temp = getNum(fruit[i].pt[ti], fruit[j].pt[tj], n);
                        if(temp > ans)
                        {
                            ans = temp;
                        }
                    }
                }
            }
        }
        printf("Case %d: %d\n", ++cnt, ans);
    }
    return 0;
}


你可能感兴趣的:(遍历,数学,连线)