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),一个节点只能有一个 ...
随机推荐
- JavaScript根据文件名后缀判断是否图片文件
//JavaScript根据文件名后缀判断是否图片文件 //图片文件的后缀名 var imgExt = new Array(".png",".jpg",&quo ...
- XCode6 开发本地化应用
使用 XCode 6 开发本地化时,第一步,不能忘记,否则在添加本地化文件时,可能会找不到简体中文. 此外,如果使用 NSLocalizedString(@"xxx", nil) ...
- awk-笔记
语法形式: awk [options] 'script' var=value file1 [file...] awk [options] -f scriptfile var=value file [f ...
- 基于GPUImage的多滤镜rtmp直播推流
之前做过开源videocore的推流改进:1)加入了美颜滤镜; 2) 加入了librtmp替换原来过于简单的rtmpclient: 后来听朋友说,在videocore上面进行opengl修改,加入新的 ...
- django url路径与模板中样式相对路径的问题
static目录下有css和js及image等文件夹,里面放置网站的一些静态文件,static位于网站根目录下,django中配置静态文件这个就细说,网上都有,昨天在添加新内容时发现一个问题,我的ur ...
- hibernate 数据处理
1.Hibernate的配置文件 Hibernate.cfg.xml Dept.hbm.xml 2.CRUD的方法名称和参数类型 Save(Object obj) Delete(Object obj) ...
- angular的跨域(angular百度下拉提示模拟)和angular选项卡
1.angular中$http的服务: $http.get(url,{params:{参数}}).success().error(); $http.post(url,{params:{参数}}).su ...
- sqlite常用查询
做的小工具用到了sqlite,在查询上较sqlserver还是稍有差异,将常用操作汇总一下,慢慢收集和整理. --查询版本SELECT sqlite_version() AS 'SQLite Vers ...
- 【笔记3】用pandas实现矩阵数据格式的推荐算法 (基于用户的协同)
原书作者使用字典dict实现推荐算法,并且惊叹于18行代码实现了向量的余弦夹角公式. 我用pandas实现相同的公式只要3行. 特别说明:本篇笔记是针对矩阵数据,下篇笔记是针对条目数据. ''' 基于 ...
- MongoDB之分片集群与复制集
分片集群 1.1.概念 分片集群是将数据存储在多台机器上的操作,主要由查询路由mongos.分片.配置服务器组成. ●查询路由根据配置服务器上的元数据将请求分发到相应的分片上,本身不存储集群的元数据, ...