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),一个节点只能有一个 ...
随机推荐
- Linux cut命令
[root@wang /]# cat /etc/passwd root:x:::root:/root:/bin/bash bin:x:::bin:/bin:/sbin/nologin daemon:x ...
- linux中offsetof与container_of宏定义
linux内核中offsetof与container_of的宏定义 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->M ...
- awk-实践
实际中遇到的问题 字符串截取函数 substr #!/usr/bin/awk #author:zhaoyingnan #filename:substr.awk #substr 函数 #|awk -f ...
- Neutron 理解 (1): Neutron 所实现的虚拟化网络 [How Netruon Virtualizes Network]
学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...
- zookeeper原理
Zookeeper与paxos算法:http://www.riaos.com/ria/11299 Paxos算法1:http://blog.csdn.net/chen77716/article/det ...
- 【Windows】用信号量实现生产者-消费者模型
线程并发的生产者-消费者模型: 1.两个进程对同一个内存资源进行操作,一个是生产者,一个是消费者. 2.生产者往共享内存资源填充数据,如果区域满,则等待消费者消费数据. 3.消费者从共享内存资源取数据 ...
- Socket
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 以J2SDK-1.3为例,Socket和ServerSocket类库位于 ...
- 关于ES6新增的东西(二)
六.原生Promise 就是一个对象,用来传递异步操作的数据(消息) pending(等待.处理中)-> Resolve(完成.fullFilled) -> Rejected(拒绝.失败) ...
- PHP开发工具+电子书+视频教程等资料下载汇总
本汇总帖包括如下内容: PHP开发工具.PHP IDE PHP学习资源 基础.进阶类 PHP学习资源 高级及应用类 经典PHP视频教程系列 1. PHP开发工具.PHP IDE: PHP开发工具:Ze ...
- Zencart视频教程 Zencart模板制作教程视频 Zencart仿站教程资料
Zen Cart是国外一个免费的.界面友好,开放式源码的购物车软件,是目前外贸行业使用最为广泛的网站程序.本仿站技术需要你有一定的html和css基础,易学易懂,一步一步地教你操作和使用Zen Car ...