poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399
http://acm.hit.edu.cn/hoj/problem/view?id=1037
题意:
在一个最多200*200的minecraft方块地图上(由很多1*1*1的方块搭起来的地图,最高5000),其中两块分别有高0.5米的激光塔,有一个高0.5米的机器人要从其中一个激光塔走到另一个。要求只能走相邻4个方向,每次不能爬上超过1格或跳下超过3格(咦,好像真的很像minecraft),要求每走到一个格子,机器人站在在这个格子的中心,能直接接收到至少一个激光塔照射(机器人的头顶与激光塔的顶部连成的直线没有被地形挡住)。
还有就是,地形有缝隙,例如:
1 9
9 1
这样的2*2的地图,在两个高度为1的地形上是可以互相接收到激光的,因为两个9之间有条缝。
题解:
宽搜走路,难点在于判断一格是否能走。
最关键的函数:判断两个格子A、B之间是否被挡。
可分为两部分判断:
1.以x轴为基准,x=Ax,x=Ax+1,x=Ax+2……x=Bx。针对每个x,计算得出浮点数Y(由激光在地平面上的斜率计算得到),可以通过floor(向下取整)得到整数y,得到激光经过(x,y) 和(x+1, y)两个格子之间的交界处,通过这两个格子的高度和激光当时的高度(由激光在竖直切面的斜率计算得到),判断是否被遮挡。
2.以y轴为基准,同上。
上面只说了没有通过缝隙的情况。若发现Y为整数,则是通过了缝隙,在x为轴的情况下,此时改为判断(x,floor(Y-0.5p))和(x+1,floor(Y+0.5p)),p为1或-1,与地平面斜率同号。以y为轴类似。
这个函数写对了其他就简单了。
-------------------------------------------------------------------
这题就难在判断光线可见,建议解题时画出平面图,写出代数公式,研究各种情况的通用判断方法。
程序过不了样例,就调试观察判断激光可见的过程,找到错误。
我写的时候出的错主要在x轴y轴分类讨论有问题、对缝隙情况判断有问题。
代码见下,我写得屁滚尿流,有很多地方有简化得更加清晰明了的余地,仅供参考
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define RD(x) scanf("%d",&x)
#define REP(i,n) for(i=0;i<n;i++)
const int MAXN=;
const int g[][]= {{,,,-},{-,,,}};
const double eps=1e-;
int n,m;
int a[MAXN][MAXN];
int p[][];
bool visited[MAXN][MAXN];
int seeChecked[MAXN][MAXN];
bool ok(int now[], int next[]) {
int y=next[], x=next[];
int h1=a[now[]][now[]];
int h2=a[next[]][next[]];
if(x< || y< || x>=n || y>=m)return false;
if(h2-h1> || h1-h2>)return false;
return true;
} bool canSee2Dot(int x1,int y1,int x2,int y2) {
bool re=true;
int k;
int p[][];
p[][]=x1;
p[][]=y1;
p[][]=x2;
p[][]=y2;
// printf("(%d,%d)->(%d,%d)\n",x1,y1,x2,y2);
REP(k,) {
int st0=p[][k],ed0=p[][k];
int st1=p[][k^], ed1= p[][k^];
if(st0==ed0)continue;
if(ed0<st0) {
swap(ed0,st0);
swap(ed1,st1);
}
// printf("k=%d,%d->%d\n",k,st0,ed0);
double kk=ed1-st1;
kk/=ed0-st0;
double hk=a[ed0][ed1] - a[st0][st1];
if(k==)hk=a[ed1][ed0]-a[st1][st0];
hk/=ed0-st0;
double now = st1 + 0.5 + 0.5*kk;
double nowh = a[st0][st1] + 0.5 + 0.5 * hk;
if(k==)nowh = a[st1][st0] + 0.5 + 0.5*hk;
// printf("%d,%d,%f,%f\n",st0,st1,hk,nowh);
for(int i=st0; i<ed0; i++) {
int theNow = floor(now);
int theX,theY;
double theH1,theH2;
if(fabs(now-round(now))>eps) {
if(k==) {
theX=i;
theY=theNow;
theH1=a[theX][theY];
theH2=a[theX+][theY];
} else {
theX=theNow;
theY=i;
theH1=a[theX][theY];
theH2=a[theX][theY+];
}
// printf("%d,%d,%f,%f,%f,(%f)\n",theX,theY,theH1,theH2,nowh,now); } else {
if(k==) {
theX=i;
theY=floor(now-0.5*fabs(kk)/kk);
theH1=a[theX][theY];
theH2=a[theX+][(int)floor(now+0.5*fabs(kk)/kk)];
} else {
theX=floor(now-0.5*fabs(kk)/kk);
theY=i;
theH1=a[theX][theY];
theH2=a[(int)floor(now+0.5*fabs(kk)/kk)][theY+];
}
// printf("%d,%d,%f,%f,%f,(%f)\n",theX,theY,theH1,theH2,nowh,now);
}
if(theH1>nowh || theH2>nowh) {
re=false;
break;
}
now+=kk;
nowh+=hk;
}
if(!re)break;
}
return re;
} bool canSee(int d[]) {
int x=d[], y=d[];
if(seeChecked[x][y]!=-)return seeChecked[x][y];
bool re=canSee2Dot(x,y,p[][],p[][]) || canSee2Dot(x,y,p[][],p[][]);
seeChecked[x][y]=re;
return re;
}
int farm() {
int b[MAXN*MAXN][];
int bl=,br=;
int i;
if(p[][]==p[][] && p[][]==p[][])return ;
memset(visited,,sizeof(visited));
memset(seeChecked,-,sizeof(seeChecked));
b[][]=p[][];
b[][]=p[][];
while(bl<br) {
int now[];
now[]=b[bl][];
now[]=b[bl][];
now[]=b[bl][];
// printf("now(%d,%d)\n", now[0],now[1]);
bl++;
REP(i,) {
int next[];
next[] = now[]+g[][i];
next[] = now[]+g[][i];
next[] = now[]+;
if(!visited[next[]][next[]] && ok(now,next) && canSee(next)) {
if(next[]==p[][] && next[]==p[][])return next[];
b[br][]=next[];
b[br][]=next[];
b[br][]=next[];
br++;
visited[next[]][next[]]=true;
}
}
}
return -;
} int main() {
int T,i,j;
int x;
RD(T);
while(T--) {
scanf("%d%d",&n,&m);
REP(i,n)REP(j,m)RD(a[i][j]);
scanf("%d%d%d%d",&p[][],&p[][], &p[][], &p[][]);
p[][]--;
p[][]--;
p[][]--;
p[][]--;
x = farm();
if(x!=-)printf("The shortest path is %d steps long.\n",x);
else printf("Mission impossible!\n");
}
return ;
}
poj1399 hoj1037 Direct Visibility 题解 (宽搜)的更多相关文章
- [NOIP2002] 字串变换 宽搜+深度优化
这道题硬是让我用STL水过.......而且题解里说的什么双向宽搜,交替扩展............... 这道题反正,STL用就用吧,但是状态数可以卡到千亿级别,因为这个东西是阶乘扩展的,然后我们发 ...
- 利用深搜和宽搜两种算法解决TreeView控件加载文件的问题。
利用TreeView控件加载文件,必须遍历处所有的文件和文件夹. 深搜算法用到了递归. using System; using System.Collections.Generic; using Sy ...
- POJ1426 Find The Multiple (宽搜思想)
Find The Multiple Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 24768 Accepted: 102 ...
- Colorado Potato Beetle(CF的某道) & 鬼畜宽搜
题意: 一个人在一张大图上走,给你路径与起点,求他走出的矩形面积并.(大概这个意思自行百度标题... SOL: 与其说这是一道图论题不如说是一道生动活泼的STL-vector教学.... 离散化宽搜, ...
- BZOJ_1615_[Usaco2008_Mar]_The Loathesome_Hay Baler_麻烦的干草打包机_(模拟+宽搜/深搜)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1615 一个主动轮带着一些轮子转,轮子带着轮子转,轮子带着轮子转...一个非主动轮只会被一个轮子 ...
- 【宽搜】ECNA 2015 D Rings (Codeforces GYM 100825)
题目链接: http://codeforces.com/gym/100825 题目大意: 给你一张N*N(N<=100)的图表示一个树桩,'T'为年轮,'.'为空,求每个'T'属于哪一圈年轮,空 ...
- 【宽搜】ECNA 2015 E Squawk Virus (Codeforces GYM 100825)
题目链接: http://codeforces.com/gym/100825 题目大意: N个点M条无向边,(N<=100,M<=N(N-1)/2),起始感染源S,时间T(T<10) ...
- 【拓扑】【宽搜】CSU 1084 有向无环图 (2016湖南省第十二届大学生计算机程序设计竞赛)
题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1804 题目大意: 一个有向无环图(DAG),有N个点M条有向边(N,M<=105 ...
- 【图论】【宽搜】【染色】NCPC 2014 A Ades
题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1787 题目大意: N个点M条无向边(N,M<=200000),一个节点只能有一个 ...
随机推荐
- 001.mysql安装(lnmp)
mysql官方网站:http://dev.mysql.com/downloads/ Linux环境:刚安装的32位的“最小化安装“的CentOS 6.7 mysql版本:本次实验安装的是mysql5. ...
- 【Windows编程】系列第十一篇:多文档界面框架
前面我们所举的例子中都是单文档界面框架,也就是说这个窗口里面的客户区就是一个文档界面,可以编写程序在里面输入或者绘制文本和图形输出,但是不能有出现多个文档的情况.比如下面的UltraEdit就是一个典 ...
- [Django]网页中利用ajax实现批量导入数据功能
url.py代码: url(r'^workimport/$', 'keywork.views.import_keywork', name='import_keywork') view.py代码: fr ...
- 【小白的CFD之旅】10 敲门实例
按黄师姐的说法,做好第一个案例很重要.第一个案例既可以帮助理解CFD的工作流程,还可以帮助熟悉软件的操作界面. 黄师姐推荐的入门案例来自于ANSYS官方提供的培训教程,是一个关于交叉管内流动混合的案例 ...
- MMORPG大型游戏设计与开发(服务器 游戏场景 核心详述)
核心这个词来的是多么的高深,可能我们也因为这个字眼望而却步,也就很难去掌握这部分的知识.之所以将核心放在最前面讲解,也可以看出它真的很重要,希望朋友们不会错过这个一直以来让大家不熟悉的知识,同我一起进 ...
- Leetcode study time
August 2, 2015 在http://zzk.cnblogs.com/ 用"找一找", 花了几个小时, 找出比较好的Leetcode博客. Read the leetcod ...
- NOIP2013火柴排队[逆序对]
题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2 其中 ai 表示 ...
- mysql apach php
一.MySql MySQL安装文件分为两种,一种是msi格式的,一种是zip格式的.如果是msi格式的可以直接点击安装,按照它给出的安装提示进行安装(相信大家的英文可以看懂英文提示),一般MySQL将 ...
- mysql utf8编码
做微信项目,报错 "Incorrect string value: '\\xF0\\x9F\\x98\\x8B' for column 'nickname' at row 1" 原 ...
- SQL Server2008从入门到全面精通 SQL数据库视频教程
第1章 SQL Server 2008入门知识:1.SQL SERVER 2008简介2.数据库概念3.关系数据库4.范式5.E-R模型6.SQL Server 2008体系结构7.安装IIS服务8. ...