ZZNU-OJ-2118 -(台球桌面碰来碰去,求总距离)——模拟到爆炸【超时】的不能AC的代码
ZZNU-2118 : 早安晚安,不如我先入土为安
题目描述
spring比较喜欢玩台球,因为看着台球在桌子上碰来碰去很有意思(台球撞壁反弹,入射角等于反射角),每次完美的台球入洞,都能体现他数学天才的能力。机房的大佬们当然不承认spring能力强,而是认为每次都是运气而已。
spring很不服气,但又打不过机房大佬,争执过程中聪明的渣渣宥终于想到了完美的办法,那也就是建立数学模型,交给脸红脖子粗的spring来解决。
题目给出一组(x,y),表示矩形的四个点分别为(0,0)(x,0)(0,y)(x,y),构成一个密闭的矩形,只有一个入口(也是唯一的出口)在原点也就是(0,0),假设一个点在原点按照角度(ay=bx)射入矩形中,所拥有的动能为E,每次接触墙壁并反弹所消耗的动能为W,如果射到除原点以外的三个顶点,将原路返回,并且消耗动能W。忽略摩擦力的影响,求出球在矩阵中运动的位移之和,保留两位有效数字。
输入
输入为六个正整数x,y,a,b,E,W。x,y,a,b均小于2000,E,W属于int
输出
求出球在矩阵中运动的位移之和,保留两位有效数字。
样例输入
1 1 1 1 1 1
1 1 1 1 2 1
样例输出
1.41
2.83
模拟了四个小时,WA了,瞬间原地爆炸了;
第二天接着找bug,调了后台数据看了看发现一些细节问题,做了一天的这道题,完整地复习了好多几何的知识点!!
我把超时的代码放着了,纪念一下下。
思路是对的,针对上限E=2*10^9,模拟——时间显然会超限!23333
放一组后台数据,可能会对你有所帮助——
INPUT
1 3 3 1 17 1
OUTPUT
17.92
超时的代码,大部分数据正确——
思路:
1、每一步严格分类讨论,计算出是否撞到源点(第一次例外),是否撞到其他三个顶点——具体是哪一个顶点,是否撞到四条边——具体是那一条边!然后分别根据具体情况,求出相应碰撞时的坐标和反射角等参数,进入下一次循环!
2、初始时,由一个顶点和一个ay=bx的射线方程可以推出这条射线的方程的K和b ,简单的方法就是把它延伸成一条相当长的线段来处理,只需坐标加上M和K*M即可!
3、代码精简了好几次,发现某些思路写的代码其实可以大大省去!
4、还有其他方法也阔以解决,比如:数学方法,相似比方法。
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<string>
#include<algorithm>
#define ll long long
using namespace std;
#include<math.h>
#define N 1008
#define M 10008
#define dinf 1000000.0
double X,Y,a,b,E,W;
const double eps=1e-;
#define PI 3.14159265358
struct Point
{
double x,y;
Point(double x=0.0,double y=0.0):x(x),y(y) {}
} p[];
typedef Point Vector;
struct line
{
Point e,f;
double k,b;
} L0,L[]; Vector operator-(Point a,Point b)
{
return Vector(a.x-b.x,a.y-b.y);
}
bool operator==(Point a,Point b)
{
return (fabs(a.x-b.x)<eps)&&(fabs(a.y-b.y)<eps);
}
double cross(Vector t,Vector f) //计算两个向量的叉乘 之模
{
return (t.x*f.y-t.y*f.x);
}
double cross1(Point e, Point f, Point g)///向量ef与向量eg的叉积,左边为负值, 锐角为正值
{
return cross(f-e,g-e);
} int factcover( Point e, Point f, Point g, Point h)///判断两个线段是否相交, 如果不包括端点 直接<0 包括端点为<=minn(极小值)
{
if(min(e.x,f.x)<=max(g.x,h.x)&&///要避免某一边的端点值 在另一边的延长线上
max(e.x,f.x)>=min(g.x,h.x)&&
min(e.y,f.y)<=max(g.y,h.y)&&
max(e.y,f.y)>=min(g.y,h.y)&& ///<=也可以;前四行 大大于小, 大大于小, 大大于小, 大大于小
cross1(e,f,g)*cross1(e,f,h)<0&& ///两条边相交 端点判断容易出错 便需要两条边同时进行; ///己方向量加一异点, 此行相交时结果为负值或0
cross1(e,g,h)*cross1(f,g,h)<0) ///如果两者共点 返回值也是1///轮流己方一点指向两个异点, 此行相交时结果为负值或0
return 1; ///0 0 1 1 3 3 4 4 返回0 0 0 9 9 3 3 4 4 返回1
return ; ///0 0 3 3 3 3 4 4 返回1 0 0 3 3 3 3 4 5 返回1
} void init(double x,double y) //四个顶点,四条边,初始点p0
{
p[]=Point(,);
p[]=Point(,y);
p[]=Point(x,y);
p[]=Point(x,); L[].e=p[],L[].f=p[];
L[].k=dinf;
L[].e=p[],L[].f=p[];
L[].k=;
L[].e=p[],L[].f=p[];
L[].k=dinf;
L[].e=p[],L[].f=p[];
L[].k=; } double Length(Vector A) //利用点积求向量长度
{
return sqrt(A.x*A.x+A.y*A.y);
} double DisToLine(Point P,Point A,Point B) //点到直线的距离
{
Vector v1=B-A,v2=P-A;
return fabs(cross(v1,v2))/Length(v1);
}
void factk(line &s) //将线段的边长延伸M倍
{
s.e.x+=1.0*M;
s.e.y+= s.k * M;
s.f.x-=1.0*M;
s.f.y-= s.k * M;
}
void launch(line &s,Point &p0,int begnum, double &ans) //反射,并返回碰撞数据
{
//求触碰边(角落),返回 反射后的射线S的 p0、k、b系数;
int flag=;
//先检查是否撞到了四个点上,再检查是否撞到了四条边上
for(int i=; i<=; i++) ///直接拿延长后的射线同四个顶点进行求最短距离,为0的为碰撞角
{
if(i!=begnum- && DisToLine(p[i],s.e,s.f)<eps)
{
flag=i;break;
}
} if(flag==) //本次弹射将撞到 第flag的边上
{
for(int i=;i<=;i++){ ///先平判断撞到编号为 flAG的 边上
if(i!=begnum&&factcover(s.e,s.f,L[i].e,L[i].f)==){
flag=i;
break;
}
} double newk,newb; // cout<<" 边:"<<flag;
if(flag==||flag==) //两条竖着的边
{
double x=L[flag].e.x;
double y=s.k*x+s.b;
ans+=Length(p0-Point(x,y));
p0=Point(x,y); newk=-*s.k;
newb=y-x*newk;
}
else //两条横着的矩形边
{
double y=L[flag].e.y;
double x=(y-s.b)/s.k;
ans+=Length(p0-Point(x,y));
p0=Point(x,y); newk=-*s.k;
newb=y-x*newk;
} s.k=newk;
s.b=newb;///更新反射后的射线S 的k和b
}
else
{ // cout<<" 角:"<<flag;
ans+=Length(p0-p[flag]);
p0=p[flag]; s.k=s.k;
s.b=s.b;///碰撞到四个角后原路返回,k不变!b不变!
} }
int main()
{ while(scanf("%lf",&X)!=EOF)
{
scanf("%lf%lf%lf%lf%lf",&Y,&a,&b,&E,&W);
init(X,Y);
int Time=; Point p0=Point(,); //初始起点和射线
line s;
s.k=b / a;
s.b=0.0;
double ans=0.0; while(E>)
{
++Time;
// if(Time%100000==0)printf(" Time*1e^5=%d\n",Time);
int begnum=-;
for(int i=; i>=; i--) //四个角编号为1+4--4+4
{
if(p[i]==p0){
begnum=i+;break;
} }
for(int i=; begnum==-&&i<=; i++) //四条边为1--4
{
if(DisToLine(p0,L[i].e,L[i].f)<eps)
{
begnum=i;
}
} // printf("beg=%d p0= %lf,%lf s.k=%lf s.b=%lf total_ans:%lf ",begnum,p0.x,p0.y,s.k,s.b,ans);
if(Time>&&begnum==)break;///从源点冲出去了 s.e=p0;
s.f=p0;//当前射线方程;
factk(s);//由点扩展成线 launch(s,p0,begnum,ans);//发射小球,计算出新的碰撞点存入p0中,并更改a,b
E-=W;//减去动能
}
printf("%.2lf\n",ans);
} return ;
}
(点一下写一天,bug不花一分钱)
ZZNU-OJ-2118 -(台球桌面碰来碰去,求总距离)——模拟到爆炸【超时】的不能AC的代码的更多相关文章
- ZZNU - OJ - 2080 : A+B or A-B【暴力枚举】
2080 : A+B or A-B(点击左侧标题进入zznu原题页面) 时间限制:1 Sec 内存限制:0 MiB提交:8 答案正确:3 提交 状态 讨论区 题目描述 Give you three s ...
- [ACM_模拟] ZJUT OJ 1139 七龙珠 (追及类问题,s-t图像,模拟)
Description 话说孙悟饭与小林正在与刚造访地球的赛亚人贝吉塔交战,因为连贝吉塔的手下纳巴的实力也远在他俩之上,由于差距悬殊,小林不得不设脱离战场,去寻找正在修炼中的悟空求救,而赛亚人一伙 ...
- Just Oj 2017C语言程序设计竞赛高级组A: 求近似值(矩阵快速幂)
A: 求近似值 时间限制: 1 s 内存限制: 128 MB 提交 我的状态 题目描述 求⌊(5–√+6–√)2n⌋⌊(5+6)2n⌋%9932017. 例如:n=1,(5–√+6–√)2( ...
- OI/ACM 刷题网站 人气OJ简介
SPOJ简介 SPOJ是波兰最为出色的Online Judge之一,界面和谐,题目类型也非常丰富,适合有一定基础的选手练习,对高手而言也是个提高能力的良好平台. SPOJ题目分类:class ...
- 台球游戏的核心算法和AI(2)
前言: 最近研究了box2dweb, 觉得自己编写Html5版台球游戏的时机已然成熟. 这也算是圆自己的一个愿望, 一个梦想. 承接该序列的相关博文: • 台球游戏核心算法和AI(1) 同时结合htm ...
- 【Tsinghua OJ】多米诺骨牌(domino)问题
(domino.c/cpp)[问题描述] 小牛牛对多米诺骨牌有很大兴趣,然而她的骨牌比较特别,只有黑色和白色的两种.她觉 得如果存在连续三个骨牌是同一种颜色,那么这个骨牌排列便是不美观的.现在她有n个 ...
- nw.js桌面软件开发系列 第0.1节 HTML5和桌面软件开发的碰撞
第0.1节 HTML5和桌面软件开发的碰撞 当我们谈论桌面软件开发技术的时候,你会想到什么?如果不对技术本身进行更为深入的探讨,在我的世界里,有这么多技术概念可以被罗列出来(请原谅我本质上是一个Win ...
- 如何在Windows Server 2008 上添加RD (远程桌面)会话主机配置的远程桌面授权服务器
在Windows Server系列的现存活跃产品中都默认的会开放两个随机附送的远程控制的授权,而一些特殊条件下我们需要启用多个远程终端连接,在购买了相应的授权之后,我们如何将配置好的服务器添加到远程桌 ...
- 【Java】深深跪了,OJ题目Java与C运行效率对比(附带清华北大OJ内存计算的对比)
看了园友的评论之后,我也好奇清橙OJ是怎么计算内存占用的.重新测试的情况附在原文后边. -------------------------------------- 这是切割线 ----------- ...
随机推荐
- 最新 竞网java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.竞网等10家互联网公司的校招Offer,因为某些自身原因最终选择了竞网.6.7月主要是做系统复习.项目复盘.LeetCode ...
- Spring 控制器层如何启用验证?
1.示例代码 @PostMapping("/adduser") public String addUser(@Valid User user,BindingResult bindi ...
- 岩哥带你飞——Spring 学习1&重要组件
------------------------------------------------------------------------------ 准备工作:1.创建一个web 项目 2.创 ...
- kubernetes 部署ingress
kubernetes Ingess 是有2部分组成,Ingress Controller 和Ingress服务组成,常用的Ingress Controller 是ingress-nginx,工作的原理 ...
- K8S从入门到放弃系列-(5)kubernetes集群之kube-apiserver部署
摘要: 1.kube-apiserver为是整个k8s集群中的数据总线和数据中心,提供了对集群的增删改查及watch等HTTP Rest接口 2.kube-apiserver是无状态的,虽然客户端如k ...
- MapReduce的输入文件是两个
[学习笔记] 1.对于MapReduce程序,如何输入文件是两个文件? 这一小节,我们将继续第一章大数据入门的HelloWorld例子做进一步的研究.这里,我们研究如何输入文件是两个文件.packag ...
- PAT甲级 图 相关题_C++题解
图 PAT (Advanced Level) Practice 用到图的存储方式,但没有用到图的算法的题目 目录 1122 Hamiltonian Cycle (25) 1126 Eulerian P ...
- SAS学习笔记22 t检验、卡方检验
- Qt中容器类应该如何存储对象(最好使用对象指针类型,如:QList<TestObj*>,而不要使用 QList<TestObj> 这样的定义,建议采用 智能指针QSharedPointer)
Qt提供了丰富的容器类型,如:QList.QVector.QMap等等.详细的使用方法可以参考官方文档,网上也有很多示例文章,不过大部分文章的举例都是使用基础类型:如int.QString等.如果我们 ...
- Oracle VIP说明
本篇文档,描述说明VIP的作用 1.VIP全称 virtual ip 虚拟IP 2.Oracle为啥要搞个VIP 3.两节点RAC,集群单个节点故障关闭后,VIP漂移否继续对外提供服务 一.模拟RAC ...