zoukankan      html  css  js  c++  java
  • Spring-2-B Save the Students(SPOJ AMR11B)解题报告及测试数据

    Save the Students

    Time Limit:134MS     Memory Limit:0KB     64bit IO Format:%lld & %llu

     

    Description

    Hogwarts is under attack by the Dark Lord, He-Who-Must-Not-Be-Named. To protect the students, Harry Potter must cast protective spells so that those who are protected by the spells cannot be attacked by the Dark Lord. Harry has asked all the students to gather on the vast quidditch sports field so that he can cast his spells.  The students are standing in a 2D plane at all grid points - these are the points (x,y) such that both x and y are integers (positive, negative or 0). Harry's spell can take the shapes of triangle, circle or square, and all who fall within that shape (including its boundaries) are protected. Given the types of spells and the details regarding where Harry casts the spell, output the number of people saved by Harry's spells. 

    Input (STDIN):

    The first line contains the number of test cases T. T test cases follow.

    Each case contains an integer N on the first line, denoting the number of spells Harry casts. N lines follow, each containing the description of a spell.

    If the ith spell is a triangle, then the line will be of the form "T x1 y1 x2 y2 x3 y3". Here, (x1,y1), (x2,y2) and (x3,y3) are the coordinates of the vertices of the triangle.

    If the ith spell is a circle, then the line will be of the form "C x y r". Here, (x,y) is the center and r is the radius of the circle.

    If the ith spell is a square, then the line will be of the form "S x y l". Here, (x,y) denotes the coordinates of the bottom-left corner of the square (the corner having the lowest x and y values) and l is the length of each side.

    Output (STDOUT):

    Output T lines, one for each test case, denoting the number of people Harry can save.

     

    Constraints:

    All numbers in the input are integers between 1 and 50, inclusive.

    The areas of all geometric figures will be > 0.

     

    Sample Input:

    4

    1

    C 5 5 2

    1

    S 3 3 4

    1

    T 1 1 1 3 3 1

    3

    C 10 10 3

    S 9 8 4

    T 7 9 10 8 8 10

    Sample Output:

    13

    25

    6

    34

    题解:

    1. 因为数据范围不大,避免重复计数,使用一个数组直接标记法即可。

    2. 是否在圆内的判断使用到圆心的距离,遍历范围x±r,y±r,是否在正方形内直接判断,数据范围x->x+r,y->y+r,是否在三角形内部,需要用到一定的数学知识,一般有以下两种方法,一是利用面积来判断,对于三角形ABC,任取一个点M,连接M与ABC三个顶点,构成了三个三角形,三个三角形的和若等于原三角形的和,则在内部,否则在外部,但是利用海伦公式求面积时,浮点数会引起误差,一般推荐使用另一种方法,即是计算MA*MB、MB*MC、MC*MA的大小,若这三个值同号,那么在三角形的内部,异号在外部,本文代码使用第二种方法,避免了浮点数的运算  。

    3. 避免在遍历圆内的点时出现负数,例如(x,y)=(1,1),r=3,所有输入均加上100即可。   

    以下是代码:

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <cstdio>
    using namespace std;
      
    #define ss(x) scanf("%d",&x)
    #define print(x) printf("%d
    ",x)
    #define ff(i,s,e) for(int i=s;i<e;i++)
    #define fe(i,s,e) for(int i=s;i<=e;i++)
    #define write() freopen("1.in","r",stdin)
      
    int m[210][210];
    struct Point{
        int x,y;
    }a,b,c,d;
    int x,y,r;
    int calmul(Point aa,Point bb,Point cc){  // 计算向量AB 与向量AC的叉乘
        return (bb.x-aa.x)*(cc.y-aa.y)-(cc.x-aa.x)*(bb.y-aa.y);
    }
    bool intr(int i,int j){//如果DA*DB、DB*DC、DC*DA同号,则在三角形内部
        int t1,t2,t3;
        d.x = i;d.y = j;
        t1 = calmul(d,a,b);
        t2 = calmul(d,b,c);
        t3 = calmul(d,c,a);
        if(t1<=0 && t2 <=0 && t3 <=0)return 1;
        if(t1>=0 && t2 >=0 && t3 >=0)return 1;
        return 0;
    }
    void solve(){
        char str[10];
        int n,cnt=0;
        memset(m,0,sizeof(m));
        ss(n);
        while(n--){
            scanf("%s",str);
            switch(str[0]){
            case'C'://圆通过到圆心的距离判断
                scanf("%d%d%d",&x,&y,&r);
                x+=100;y+=100;//避免坐标为负值,输入全部加上100
                fe(i,x-r,x+r)
                fe(j,y-r,y+r)
                if(!m[i][j]&& ((x-i)*(x-i)+(y-j)*(y-j)<=r*r)){
                    cnt++;
                    m[i][j]=1;
                }
                break;
            case'T'://三角形通过叉乘来判断
                scanf("%d%d%d%d%d%d",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y);
                a.x+=100;b.x+=100;c.x+=100;a.y+=100;b.y+=100;c.y+=100;
                fe(i,100,200)
                fe(j,100,200)
                if(!m[i][j] && intr(i,j)){
                    cnt++;
                    m[i][j]=1;
                }
                break;
            case'S'://正方形的判断
                scanf("%d%d%d",&x,&y,&r);
                x+=100;y+=100;
                fe(i,x,x+r)
                fe(j,y,y+r)
                if(!m[i][j]){
                    cnt++;
                    m[i][j]=1;
                }
            }
        }
        print(cnt);
    }
    int main(){
        //write();
        int T;
        ss(T);
        while(T--){
            solve();
        }
    }
    

      

     
  • 相关阅读:
    Python 字典方法(.get .item)
    Python格式化输出
    R sprintf函数
    r 中sub() gsub()等匹配与替换函数
    R read.csv数据框
    C#中使用ref、out、params例子
    C#中的三种委托方式:Func委托,Action委托,Predicate委托
    tfs强制撤销解锁命令
    Json序列化与反序列化
    XPath语法在C#中使用XPath示例第二讲
  • 原文地址:https://www.cnblogs.com/gzdaijie/p/4299015.html
Copyright © 2011-2022 走看看