题目:传送门
思路:主要就是难在模型转换,只要看破,这道题就是很简单的最短路。s点t点以及每束光线的源点建立边,边的权值就是穿过这条边的光束数量。之后就是spfa跑一下s到t的最短路。在判断线段和射线相交的时候卡了很久。。。之前用一般式,连案例都跑不出,后来才想到斜率不存在的时候没有判断╮(╯▽╰)╭,然后直接换了参数方程写就不用判断斜率了。
下面是代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#define N 210
#define INF 0x3f3f3f3f
#define LL long long
#define EPS 1e-8
using namespace std;
struct point{
double x,y;
point(){};
point(double x,double y){
this->x=x;
this->y=y;
}
};
struct line{
point s,t;
line(){};
line(point s,point t){
this->s=s;
this->t=t;
}
}l[205];
int n;
point s,t;
int g[N][N];
int dist[N];
bool visit[N];
double kross(point a,point b)
{
return a.x*b.y-a.y*b.x;
}
bool pd(line a,line b)
{
/*if(a.s.x==b.s.x&&a.s.y==b.s.y||a.t.x==b.s.x&&a.t.y==b.s.y)
return false;*/
point d1=point(a.t.x-a.s.x,a.t.y-a.s.y);
//cout<<d1.x<<' '<<d1.y<<endl;
point d2=point(b.t.x-b.s.x,b.t.y-b.s.y);
//cout<<d2.x<<' '<<d2.y<<endl;
point d3=point(a.s.x-b.s.x,a.s.y-b.s.y);
//cout<<d3.x<<' '<<d3.y<<endl;
double d1d2=kross(d2,d1);
if(d1d2==0) return false;
double k1=kross(d3,d2)/d1d2;
double k2=kross(d3,d1)/d1d2;
//cout<<k1<<' '<<k2<<endl;
if(k1>0&&k1<1&&k2>0)
return true;
else
return false;
}
int get_points(point a,point b)
{
int res=0;
for(int i=1;i<=n;i++)
{
if(pd(line(a,b),l[i]))
res++;
}
return res;
}
void build_edge()
{
for(int i=0;i<n+3;i++)
{
for(int j=0;j<n+3;j++)
g[i][j]=INF;
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
g[i][j]=g[j][i]=get_points(l[i].s,l[j].s);
}
g[n+1][i]=g[i][n+1]=get_points(s,l[i].s);
g[n+2][i]=g[i][n+2]=get_points(t,l[i].s);
}
g[n+1][n+2]=g[n+2][n+1]=get_points(s,t);
}
void spfa(int start) {
queue<int> Q;
int i, now;
memset(visit, false, sizeof(visit));
for (i = 1; i <= n+2; i++){
dist[i] = INF;
}
dist[start] = 0;
Q.push(start);
visit[start] = true;
while (!Q.empty()) {
now = Q.front();
Q.pop();
visit[now] = false;
for (i = 1; i <= n+2; i++) {
if (dist[i] > dist[now] + g[now][i]) {
dist[i] = dist[now] + g[now][i];
if (visit[i] == 0) {
Q.push(i);
visit[i] = true;
}
}
}
}
}
int main()
{
while(~scanf("%d",&n),n)
{
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&l[i].s.x,&l[i].s.y,&l[i].t.x,&l[i].t.y);
}
scanf("%lf%lf%lf%lf",&s.x,&s.y,&t.x,&t.y);
build_edge();
//cout<<pd(line(l[2].s,t),l[3])<<endl;
/*for(int i=1;i<=n+2;i++)
{
for(int j=1;j<=n+2;j++)
cout<<g[i][j]<<' ';
cout<<endl;
}*/
spfa(n+1);
printf("%d\n",dist[n+2]);
}
}