光影切割问题

  问题描述:

不少人很爱玩游戏,例如 CS 。 游戏设计也成为程序开发的热点之一,我们假设要设计破旧仓库之类的场景作为战争游戏的背景。仓库的地面会因为阳光从屋顶的漏洞或者窗口照射进来而形成许多光照区域和阴影区域。为了简单起见,假设不同区域的边界都是直线 , 我们把这些直线都叫做“光影线”,并且不存在三条光影线相交于一点的情况。

那么,如果我们需要快速计算某个时刻,在 X 坐标[ A, B] 区间的地板上被光影划分成多少块。如何才能写出算法来计算呢?

 【解法一】

这个问题需要先自己归纳寻找规律。由于不存在三直线交于一点的情况,一些情况可以不用考虑。题目要求的是在A,B区间内,通过尝试可以找到规律。如果只有一条线,那么分割成两块空间。如果有两条线,可能相交,也可能不相交(只要在A到B这个区间内不相交就行)。如果相交,那么就分割成四块,否则是三块。

以此类推就会发现,分割块数=线的数量+在这个区间内的交点数量+1,其中1为区间初始平面个数。

也就是说,只需要判断在这个区间内的交点有几个,经过这个区间的线有几条即可。我们可以先进行一次预处理,计算出所有交点的位置,然后在每一次查询时就可以很快查找到了。

【解法二】

  进一步分析图1-12的右图可以知道,区域内的交点数目就等于一个边界上交点顺序相对另一个边界交点顺序的逆序总数(这里利用到条件“没有三条直线相交于一个点”)。在右图中,左边界顺序为(a,b,c),右边界为(c,b,a),假设a=1,b=2,c=3,那么(c,b,a)=(3,2,1),它的逆序数为3。

  因此,问题转化为求一个N个元素的数组的逆序数。

  最直接的求解逆序数方法还是O(N2),如果用分治的策略可以将时间复杂度降为O(N*log2N),求N个元素的逆序数的分治思想如下,首先求前N/2个元素的逆序数,再求后N/2个元素的逆序数,最后在排序过程中合并前后两部分之间的逆序数。

  【方法一】直接求解逆序数算法:

package chapter1youxizhileRevertSortCount;
/*** 光影切割问题* 寻找逆序数的直接求法* @author DELL**/
public class RevertSortCount1 {private int[] a;  //寻找逆序数的数组//构造方法public RevertSortCount1(int[] a){this.a = a;}/*** 直接寻找逆序数* @return*/public int count(){System.out.print("逆序对为:");int i,j,cnt=0;for(i=0;i<a.length;i++){for(j=0;j<i;j++){if(a[j]>a[i]){cnt++;System.out.print("("+a[j]+", "+a[i]+") ");}}}System.out.println();return cnt;}public static void main(String[] args) {int[] a = {3, 5, 4, 8, 2, 6, 9};RevertSortCount1 rsc = new RevertSortCount1(a);System.out.println("逆序数为:"+rsc.count());}}

程序运行结果如下:

逆序对为:(5, 4) (3, 2) (5, 2) (4, 2) (8, 2) (8, 6)
逆序数为:6

 【方法二】归并的思想

package chapter1youxizhileRevertSortCount;
/*** 光影切割问题* 寻找逆序数的归并算法* @author DELL**/
public class RevertSortCount2 {private int[] a;  //寻找逆序数的数组private int count = 0; //逆序数//构造方法public RevertSortCount2(int[] a){this.a = a;System.out.print("逆序对为:");mergeSort(a,0,a.length-1);}/*** 归并排序寻找逆序数* 合并两个有序数组* @param a  待排序数组* @param first 第一个有序数组在a中的起始位置* @param mid    第一个数组的最后一个位置* @param last  第二个数组的最后一个位置*/public void merge(int[] a, int first, int mid, int last){int[] b;  //临时数组b = new int[a.length];int i=first,j=mid+1,k=first;while(i<=mid&&j<=last){if(a[i]<=a[j]){b[k++]=a[i++];}else{for(int l=i;l<=mid;l++){  //输出逆序对System.out.print("("+a[l]+", "+a[j]+") ");}                b[k++]=a[j++];count += mid-i+1;   //记录逆序数
            }}while(i<=mid){  //把剩余的添加到b中b[k++]=a[i++];}while(j<=last){    //把剩余的添加到b中b[k++]=a[j++];}for(i=first;i<=last;i++){ //把排好序的数组重新赋给aa[i]=b[i];}}/*** 归并排序* @param a 待排序数组* @param first 数组起始位置* @param last 数组结束位置*/public void mergeSort(int[] a, int first, int last){int mid = (first+last)/2;  //获取中间位置if(first==last)return;mergeSort(a,first,mid);mergeSort(a,mid+1,last);merge(a,first,mid,last);}public static void main(String[] args) {int[] a = {3, 5, 4, 8, 2, 6, 9};System.out.print("原数组为:");for(int i=0;i<a.length;i++){System.out.print(a[i]+" ");}System.out.println();RevertSortCount2 rsc = new RevertSortCount2(a);System.out.print("\n排好序的数组为:");for(int i=0;i<a.length;i++){System.out.print(a[i]+" ");}System.out.println();System.out.println("逆序数为:"+rsc.count);}}

程序运行结果如下:

原数组为:3 5 4 8 2 6 9
逆序对为:(5, 4) (3, 2) (4, 2) (5, 2) (8, 2) (8, 6)
排好序的数组为:2 3 4 5 6 8 9
逆序数为:6

其它参考链接:

精选的一些《编程之美》相关资料

读书笔记之编程之美 - 1.7 光影切割问题

编程之美-光影切割问题

逆序数的几种求法

转载于:https://www.cnblogs.com/gaopeng527/p/4604787.html

第1章 游戏之乐——光影切割问题相关推荐

  1. 编程之美-第1章 游戏之乐

    1. 使CPU占有率画出正弦曲线 linux下的代码: #if 0 /** Q1.1*/ int get_tick_count(){struct timeval tv;gettimeofday(&am ...

  2. 第1章 游戏之乐——连连看游戏设计

    连连看游戏设计 连连看是一种很受大家欢迎的小游戏.微软亚洲研究院的实习生们就曾经开发过一个类似的游戏--Microsoft Link-up.    图1-17为Microsoft Link-up的一个 ...

  3. 第1章 游戏之乐——构造数独

    构造数独 1. 问题 构造一个9*9的方格矩阵,玩家要在每个方格中,分别填上1至9的任意一个数字,让整个棋盘每一列.每一行以及每一个3*3的小矩阵中的数字都不重复. 2. 求解 用转置的方法生成数独数 ...

  4. 第1章 游戏之乐——快速找出故障机器

    转载:编程之美_1.5_快速找出机器故障 题目:假设一个机器只存储一个标号为ID的记录,假设每份数据保存2个备份,这样就有2个机器存储了相同的数据.其中ID是小于10亿的整数 问题1.在某个时间,如果 ...

  5. 小飞的电梯调度算法,光影切割问题编程之美

    小飞的电梯调度算法: 1.8问题描述: 小飞是实习程序员,下班高峰期时电梯的每层都有人上下,等电梯是件烦人的事情. 小飞有个方案:电梯每次计算里面的人,和上的楼层,从而统计出在哪一层停,该上楼的出电梯 ...

  6. swift语言实战晋级-第9章 游戏实战-跑酷熊猫-7-8 移动平台的算法

    原文:swift语言实战晋级-第9章 游戏实战-跑酷熊猫-7-8 移动平台的算法 在上个小节,我们完成了平台的产生.那么我们来实现一下让平台移动.平台的移动,我们只需要在平台工厂类中写好移动的方法,然 ...

  7. 《Splunk智能运维实战》——第1章 游戏时间——导入数据 1.1 简介

    本节书摘来自华章计算机<Splunk智能运维实战>一书中的第1章,第1.1节,作者 [美]乔史·戴昆(Josh Diakun),保罗R.约翰逊(Paul R. Johnson),德莱克·默 ...

  8. 游戏感:虚拟感觉的游戏设计师指南——第二章 游戏感与人类感知能力

    这是一本游戏设计方面的好书 转自天:天之虹的博客:http://blog.sina.com.cn/jackiechueng 感谢天之虹的无私奉献 Word版可到本人的资源中下载 第二章游戏感与人类感知 ...

  9. 《游戏设计艺术(第2版)》——学习笔记(8)第8章 游戏通过迭代提高

    <游戏设计艺术(第2版)>学习笔记(8) 第8章 游戏通过迭代提高 选择创意 八项测试 迭代规则 软件工程的简短历史 危险--瀑布--保留 巴里·伯姆爱你 敏捷宣言 风险评估与原型设计 制 ...

  10. 《游戏设计艺术(第2版)》——学习笔记(7)第7章 游戏始于一个创意

    <游戏设计艺术(第2版)>学习笔记(7) 第7章 游戏始于一个创意 灵感 陈述问题 如何睡眠 你的无声伙伴 潜意识建议1:给予关注 潜意识建议2:记录你的创意 潜意识建议3:(明智的)满足 ...

最新文章

  1. Phpcms V9当前栏目及所有二级栏目下内容调用标签
  2. python wait之后怎么起起来_python wait方法_Python条件类| 带有示例的wait()方法
  3. java x86 模拟,Java模拟实现百度文档在线浏览
  4. 【Qt】New Features in Qt 5.15
  5. win10必须禁用的服务_7寸屏的迷你电脑,就算是8GB运行内存,也必须关闭的系统选项...
  6. 【转】MVVM大比拼小结
  7. 小故事分享:千里马与苍蝇的故事
  8. jedis操作set_Jedis对redis的五大类型操作代码详解
  9. 【摘转留用】35前要考虑的
  10. java 枚举 注解_Java枚举类和注解梳理
  11. 京瓷300i_kyocera cs 300i kx驱动下载
  12. 显微镜下的大明内容_《显微镜下的大明》读后感1000字
  13. 【073】我的wifi卡片-分享wifi密码一扫就好
  14. 深入浅出移动直播技术之帧率、码率和分辨率
  15. 记2017第八届蓝桥杯决赛(国赛)—北京三日游
  16. 怎么检查新买的mac是不是原封正品
  17. 3D打印无人机等无人设备6——谈一谈从设计到实践的分分合合,模型如何合并与拆分?
  18. Cisco设备的启动以及交换机的介绍
  19. 论文解读:《Linguistically Motivated Parallel Data Augmentation for Code-switch Language Model》
  20. 最新kali之pixiewps

热门文章

  1. 使用PowerDesigner
  2. hibernate数据类型之间的映射关系
  3. mybatis报错解决
  4. 【渝粤教育】21秋期末考试标准的研制与编制★10003k1
  5. 【渝粤教育】国家开放大学2018年春季 0221-22T数字电子电路 参考试题
  6. 控制系统数字仿真与CAD-第二次实验-附完整代码
  7. java 实现类似spring的可配置的AOP框架
  8. VMware虚拟机下Ubuntu安装VMware Tools详解
  9. [转]引用 VC 对话框设置位图背景并透明控件
  10. Day14 - Ruby比一比:#each #map和#collect method