vijos 1288 箱子游戏 计算几何

背景

hzy是箱子迷,他很喜欢摆放箱子,这次他邀请zdq,skoier一起来玩game...

描述

地板上有一个正方形的大箱子和许多三角型的小箱子。所有的小箱子都在大箱子里面,同时,一些三角形的小箱子可能在另一些小箱子里面,但是所有的小箱子都不相交。你在大箱子里面随机选一个点,它恰好在inBox个小箱子里的概率是多少?我们知道,大箱子的边都平行于坐标轴,并且有两个顶点位于(0,0)和(100,100)。

格式

输入格式

输入的第一行包含两个正整数n和inBox(0 <= inBox <= n <=50),表示小箱子的个数以及随机点在多少个小箱子里面。接下来n行每行包含6个整数x1,y1,x2,y2,x3,y3,表示一个小箱子的三个顶点的坐标。

输出格式

输出仅包含一个数字,表示你计算的概率,精确到小数点后5位。

样例输入1[复制]

2 1
0 0 20 0 0 10
1 1 6 1 1 5

样例输出1[复制]

0.00900

样例输入2[复制]

4 0
0 0 10 0 0 20
0 100 0 90 20 100
50 50 60 60 50 70
51 55 55 60 51 65

样例输出2[复制]

0.97000

题意:给出很多三角形,问某个点存在于k个三角形内部的概率为多少

思路:叉积判断两个三角形是否为内含关系,并可以拿来求三角形面积,从三角形面积大到小和是否为内含关系来建一颗树,最后DFS求出k层三角形的面积-k+1层三角形的面积,最后除以总面积即可。

/** @Date    : 2016-12-12-21.02
  * @Author  : Lweleth ([email protected])
  * @Link    : https://github.com/
  * @Version :
  */
#include<bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-6;

typedef struct str
{
    double x, y;
}pot;

struct trg
{
    str p1, p2, p3;
};

struct node
{
    trg tri;
    vector son;
    int h;
};

double cross(str &a, str &b)
{
    return a.x*b.y - a.y*b.x;
}

str creatstr(str &a, str &b)
{
    str x;
    x.x = a.x - b.x;
    x.y = a.y - b.y;
    return x;
}

int isin(trg &a, trg &b)
{
    str s1 = creatstr(b.p1, a.p1);
    str s2 = creatstr(b.p1, a.p2);
    str s3 = creatstr(b.p1, a.p3);
    double r1 = cross(s1, s2);
    double r2 = cross(s2, s3);
    double r3 = cross(s3, s1);
    double ep1 = fabs(r1);
    double ep2 = fabs(r2);
    double ep3 = fabs(r3);
    if( ((r1 > 0 && r2 > 0 && r3 > 0 )||(r1 < 0 && r2 < 0 && r3 < 0 )||(ep1 < eps || ep2 < eps || ep3 < eps)) != 1)
        return 0;

    s1 = creatstr(b.p2, a.p1);
    s2 = creatstr(b.p2, a.p2);
    s3 = creatstr(b.p2, a.p3);
    r1 = cross(s1, s2);
    r2 = cross(s2, s3);
    r3 = cross(s3, s1);
    ep1 = fabs(r1);
    ep2 = fabs(r2);
    ep3 = fabs(r3);
    if( ((r1 > 0 && r2 > 0 && r3 > 0 )||(r1 < 0 && r2 < 0 && r3 < 0 )||(ep1 < eps || ep2 < eps || ep3 < eps)) != 1)
        return 0;

    s1 = creatstr(b.p3, a.p1);
    s2 = creatstr(b.p3, a.p2);
    s3 = creatstr(b.p3, a.p3);
    r1 = cross(s1, s2);
    r2 = cross(s2, s3);
    r3 = cross(s3, s1);
    ep1 = fabs(r1);
    ep2 = fabs(r2);
    ep3 = fabs(r3);
    if( ((r1 > 0 && r2 > 0 && r3 > 0 )||(r1 < 0 && r2 < 0 && r3 < 0 )||(ep1 < eps || ep2 < eps || ep3 < eps)) != 1)
        return 0;

    else return 1;
}

double calarea(trg &a)
{
    str s1 = creatstr(a.p1, a.p2);
    str s2 = creatstr(a.p2, a.p3);
    double siz = fabs(cross(s1 , s2)) / 2.00000;
    return siz;
}

node* insertT(node *h, trg &a)
{
    node *t;
    if(h == NULL)//到叶子时返回
    {
        t = new node;
        t->tri = a;
        t->h = 0;
        return t;
    }
    for(int i = 0; i < h->son.size(); i++)
    {
        t = h->son[i];
        if(isin(t->tri, a))
        {
            h->son[i] = insertT(t, a);  //递归建树
            h->son[i]->h = h->h + 1;
            return h;
        }
    }
    int p = h->son.size();
    h->son.PB(insertT(NULL, a));
    h->son[p]->h = h->h + 1;
    return h;
}

double dfs(node *h, int k)
{
    if (h == NULL)
        return 0;

    if (h->h < k)
    {
        double sum = 0;
        for (int i = 0; i < h->son.size(); i++)
            sum += dfs(h->son[i], k);
        return sum;
    }
    else
    {
        double ins = 0;
        for (int i = 0; i < h->son.size(); i++)
            ins += calarea(h->son[i]->tri);
        return calarea(h->tri) - ins;
    }
}

int cmp(trg a,  trg b)
{
    return calarea(a) > calarea(b);
}

int main()
{
    trg tri[1010];
    int n, k;
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; i++)
    {
        double a, b, c, d, e, f;
        scanf("%lf%lf%lf%lf%lf%lf", &a, &b, &c, &d, &e, &f);
        tri[i].p1.x = a;
        tri[i].p1.y = b;
        tri[i].p2.x = c;
        tri[i].p2.y = d;
        tri[i].p3.x = e;
        tri[i].p3.y = f;
    }
    sort(tri + 1, tri + 1 + n, cmp);
    tri[0].p1.x = -1000;
    tri[0].p1.y = -1000;
    tri[0].p2.x = 1000;
    tri[0].p2.y = -1000;
    tri[0].p3.x = 1000;
    tri[0].p3.y = 2000;
    node *head = NULL;
    head = insertT(head, tri[0]);

    for(int i = 1; i <= n; i++)
    {
        head = insertT(head, tri[i]);

    }
    double ans = 0;
    if(k == 0)
    {
        double t = 0;
        for(int i = 0; i < head->son.size(); i++)
        {
            t += calarea(head->son[i]->tri);
        }
        ans = 10000 - t;
    }
    else ans = dfs(head, k);

    ans /= 10000.000;
    printf("%.5lf\n", ans);
    return 0;
}
时间: 2024-12-30 20:21:59

vijos 1288 箱子游戏 计算几何的相关文章

JavaScript写一个小乌龟推箱子游戏

推箱子游戏是老游戏了, 网上有各种各样的版本, 说下推箱子游戏的简单实现,以及我找到的一些参考视频和实例: 推箱子游戏的在线DEMO : 打开 如下是效果图: 这个拖箱子游戏做了移动端的适配, 我使用了zepto的touch模块, 通过手指滑动屏幕就可以控制乌龟走不同的方向: 因为推箱子这个游戏比较简单, 直接用了过程式的方式写代码, 模块也就是两个View 和 Model, 剩下就是用户的事件Controller, 用户每一次按下键盘的方向键都会改变数据模型的数据,然后重新生成游戏的静态htm

致佳音: 推箱子游戏自动求解算法设计(四)

这一节是本文的核心内容,即推箱子游戏求解算法的设计思路过程 前面已经说过过,判断局面重复的最好标准不是局面完全一致,而是坐标排序相同且角色坐标通行 如下图,角色无论怎么移动,不推动箱子的时候,都能回到原来的位置,算作同一个局面: 再如下图,两个箱子互换位置,结果与没有移动箱子是一样的,所以排序箱子坐标以后一致,还是相同局面 问:有必要判断局面重复吗?是不是只是提升一下效率? 答:不是为了提升效率,而是为了能解出来,如果使用递归,重复的局面反复耗尽堆栈,而队列则耗尽内存 正如上图,反复推这两个箱子

致佳音: 推箱子游戏自己主动求解算法设计(四)

这一节是本文的核心内容,即推箱子游戏求解算法的设计思路过程 前面已经说过过,推断局面反复的最好标准不是局面全然一致,而是坐标排序同样且角色坐标通行 例如以下图.角色不管怎么移动,不推动箱子的时候.都能回到原来的位置.算作同一个局面: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcHJzbmlwZXI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast"

推箱子游戏

本游戏为推箱子游戏,即通过移动方向键来控制小人去推动箱子,直到把所有的箱子都推动到各个目标中.游戏需要在人物行走过程中无法穿越墙和箱子,并在有限的范围中放好各箱子,且每次只能搬运一个箱子.所基于的语言是8086汇编,使用的编译环境是唐都的集中开发环境TD-PIT. 本次设计的基本思想是通过将不同的元素(墙.路.箱子.人.目标位)抽象为不同的矩阵,然后将所设计的地图描抽象成一个控制矩阵来控制图像的显示,每一个控制矩阵块代表一个元素,我们通过不断刷新控制矩阵来达到显示人物移动及推箱子的效果. 1.1

jQuery版推箱子游戏详解和源码

前言 偶然间看到很多用js写游戏的感觉很炫酷的样子,所以就想试试,就看了一些资料和某前端站点的视屏.于是乎就自己动手实践了一下,上推箱子截图 感觉很丑陋,但是功能是实现了.再说貌似大多都是这样的吧,这一关其实还是有点难度的,我做完之后想检测一下下一关正确么,居然还玩了以后才通关. 如果你看到这张图让你想起了你童年的回忆,说明你老了,这里可以试玩一下(很遗憾没有链接地址,最后又源码可以下载). css布局 主要考虑的是地图是怎么动态生成的,地图中有灰色的,还有墙,箱子,蓝色,红色背景,人物.先看c

C++学习(九)之 项目 推箱子游戏

游戏制作 推箱子 步骤分析 1.模板 2.模板分析 组成元素: 空地 墙 人 目的地 箱子 背景 3.如何操作 通过WASD键盘操作人,推着箱子,到达目的地,游戏结束,如果箱子卡在死角则游戏失败 4.如何绘制地图 通过数组来存储绘制 数组中 0表示空地 1表示墙 2表示人 3表示箱子 4表示目的地 移动时 人在目的地上:人+目的地=2+4=6 箱子在目的地上:箱子+目的地=3+4+7 (⊙o⊙)-额  大概就这样吧 (其实就是自己做的时候的一些笔记,以后用的时候再看吧) 1 //事先先改多字节

C语言学习教程:搬箱子游戏开发源码分享

C语言学习教程:搬箱子游戏开发源码分享,推箱子游戏的规则非常简单,就是用尽量少的推动或移动把所有箱子都推到目标点上.箱子只能推动而不能拉动:一次只能推动一个箱子. 源码截图,由于有点多就不一 一截图了,完整的可以加我交流裙免费领取,这里推荐一下我建的C/C++语言学习交流秋秋裙,前三位是:110,中间三位是:355,最后三位是:025,为了让学习变得轻松,高效!给大家分享一套教学资源,帮助大家在成为C/C++语言开发高手的道路上披荆斩棘,群内每晚八点免费直播授课,讲解C/C++语言案例,同时还有

用C写一个简单的推箱子游戏(一)

我现在在读大二,我们有一门课程叫<操作系统>,课程考查要求我们可以写一段程序或者写Windows.iOS.Mac的发展历程.后面我结合网上的资料参考,就想用自己之前简单学过的C写一关的推箱子小程序. 这一程序主要用到了C语言中的二维数组,头文件#include<conio.h>(因为要调用getch()函数以记录输入内容),switch函数等. 一.     功能概述 a)   游戏规则概述 玩家通过键盘输入W.S.A.D四键或者“↑”.“↓”.“←”.“→”四个方向键推动箱子,而

致佳音: 推箱子游戏自动求解算法设计(二)

这一个小节我们说一说传说中的A×算法,其实之前也上传过类似的小件件,这里我们就去剖析一下它 毕竟在游戏程序,我们要从一点移动到另一点,并得到最短路程的轨迹,类似这种算法还有好几种,执行效率都差不多,不过大多不能得到轨迹 首先,从一点移动到另一点,最快就是直接走过去了,就像小男生爱上小女生,最好的办法就是直接走到她面前说:我爱你 不过理想状态,几乎是没有的,弯路那是必然的经过,有曲线,其实更美-- 那么弯路该怎么走呢,是不是先去背景看下毛主席,再去三亚晒个太阳,再回来告诉她外面的世界好美,不,不,