http://poj.org/problem?id=3985
题目大意:
给一个起点和一个终点 给出从个点出发可走的方向(小于等于10) 问最少多少步走到终点
分析:
这个题目是有点厉害了 之前没用过hash表 有现学了一下hash
推荐篇hash的博客:
http://www.cnblogs.com/dolphin0520/archive/2012/09/28/2700000.html
然后说一下思路 关键在于剪枝 怎么剪枝呢 主要是两部分
首先一定要是从起点向终点终点走 相反走的点舍弃掉 做题的时候想到了 但水平low不会写看了下题解 利用三角形的三边关系就可以判断新的点的走向
其次 距离起点和终点所在直线较远的点舍弃 到底多远呢 方向一步所走最大值
hash表存下每个点 然后bfs就行了
AC代码:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include<list>
#include <bitset>
#include <climits>
#include <algorithm>
#define gcd(a,b) __gcd(a,b)
#define mset(a,n) memset(a,n,sizeof(a))
#define FIN freopen("input","r",stdin)
#define FOUT freopen("output","w",stdout)
typedef long long LL;
const LL mod=1e9+7;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
const int prime=999997;
using namespace std;
int dir[20][2];// 方向数组
int sx,sy,ex,ey;
int n;
int a,b,c;// 直线方程系数
double maxn;
int cnt;
int head[prime];
struct node{// 点
int tx,ty;
int step;
};
struct node2{// 链式钱向星存相同Hash地址的点
int x,y;
int next;
}edge[1000000];
int Hash(int x,int y){// 求Hash地址
return (((x<<15)^y)%prime+prime)%prime;
}
int addedge(int u,int x,int y){// 存相同Hash地址的点
for (int i=head[u];i!=-1;i=edge[i].next)// 之前存在过的点不再计算
if (edge[i].x==x&&edge[i].y==y) return 0;
edge[cnt].x=x;
edge[cnt].y=y;
edge[cnt].next=head[u];
head[u]=cnt++;
return 1;
}
int judge(int x,int y){
double temp=sqrt(a*a+b*b);
// 起点、终点、要判断的点构成的三角形三条边
double A=((sx-x)*(sx-x)+(sy-y)*(sy-y));
double B=((ex-x)*(ex-x)+(ey-y)*(ey-y));
double C=((ex-sx)*(ex-sx)+(ey-sy)*(ey-sy));
if (A+C<B||B+C<A) return 0;// 向相反方向走
double length=fabs(a*x+b*y+c)/temp;// 距离直线距离
if (length<=maxn) return 1;
return 0;
}
void bfs(){
queue<node> Q;
node start;
start.step=0;
start.tx=sx;
start.ty=sy;
Q.push(start);
addedge(Hash(sx,sy),sx,sy);
while (!Q.empty()){
node temp=Q.front();
Q.pop();
if (temp.tx==ex&&temp.ty==ey){
printf ("%d\n",temp.step);
return ;
}
for (int i=0;i<n;i++){
node tt=temp;
tt.tx+=dir[i][0];
tt.ty+=dir[i][1];
if(judge(tt.tx,tt.ty)&&addedge(Hash(tt.tx,tt.ty),tt.tx,tt.ty)){
tt.step++;
Q.push(tt);
}
}
}
printf ("IMPOSSIBLE\n");
}
void Init(){
mset(head,-1); cnt=0;
scanf ("%d%d%d%d",&sx,&sy,&ex,&ey);
// 求直线方程(可以用两点式求方程然后化简成标准形式)
a=sy-ey;
b=ex-sx;
c=sx*ey-sy*ex;
maxn=0;
scanf ("%d",&n);
for (int i=0;i<n;i++) {
scanf ("%d%d",&dir[i][0],&dir[i][1]);
maxn=max(maxn,sqrt(dir[i][0]*dir[i][0]+dir[i][1]*dir[i][1]));// 偏离直线的最大值
}
}
int main (){
//FIN;
int t;
scanf ("%d",&t);
while (t--){
Init();
bfs();
}
return 0;
}