SDOI2013 逃考 計算幾何 最短路

2022-05-16 10:49:04 字數 2737 閱讀 2099

這道題看似像dp,又像圖論,結果二者都不是。

其實我看了很久都沒有看出來,果然我太蒟蒻了。

這個題,只要構建出了圖的模型就好做了,我們可以將乙個親戚與他相鄰的監視範圍有公共邊的建一條雙向邊,邊長為1,凡是監視範圍與矩陣邊界相鄰的親戚就建一條他到終點的邊,邊長也為1,然後找到最開始監視目標的那個人,以他的編號為起點,跑一邊起點到終點的最短路,就是答案了。而最短路很容易用spfa或者dijkstra演算法就得出答案了。

然而,如何建邊呢?如何確定監視範圍呢?根據題意,我們可以看出,乙個親戚的監視範圍與另乙個親戚的監視範圍的分界線就是他們倆的連線的中垂線,自己畫畫圖就知道了其實這個很像泰森多邊形(題外話,並無什麼用)。然後對於每乙個親戚的監視範圍就是他與所有其他親戚的分界線的面對他自己的半平面交,注意的是還要限制在給定的矩陣內。這樣兩兩枚舉,就在o(

n2lo

gn)' role="presentation">o(n

2log

n)o(

n2lo

gn)的時間複雜度內求出並建出圖啦!(具體看**),然後

n' role="presentation">n

n很小,就可以過了。

本蒟蒻**醜且常數炒雞大,將就看吧

#include

#include

#include

#include

#define db double

using

namespace

std;

const

int m=1e4+1;

const

int inf=0x7fffffff;

const db eps=1e-10;

int dcmp(db x)

int t,n,s,t;

//s,t表示起點終點編號

db sx,sy,bx,by;

//矩陣大小和起點座標

struct ss

}g[m<<1];

int head[m],cnt;

void add(int a,int b)

int dis[m];

bool vis[m];

int sze,que[m],pp,qq;

int spfa(int tot)}}

}return dis[t];

}//這裡我用的spfa的最短路

struct point

void in()

}po[m];

point operator +(point a,point b)

point operator -(point a,point b)

point operator *(point a,db b)

point operator /(point a,db b)

db cross(point a,point b)

db dot (point a,point b)

//計算幾何基礎啦,就不解釋了

point rotate(point a)

point getmid(point a,point b)

//rotate求逆時針旋轉向量90度

//getmid求線段中點,這兩個是求中垂線用的

struct line

line(point a,point b,int c):p(a),v(b),id(c)

bool

operator

<(line a)const

}l[m];

bool onleft(line le,point p)

point getlinecut(line a,line b)

int fi,la,vnt;

point p[m];

line q[m];

bool no[m];

void init(int a,int tot)

//初始化a號親戚的邊界

}void halfcut(int a,int tot)

if(fi1]=getlinecut(q[la],q[la-1]);

}while(fi1])) --la;

if(la-fi<=1) return;

for(int i=fi;i<=la;i++)//id記錄這條邊所對的那個親戚的編號

}//半平面交模板

void clear()

//初始化,因為有多組資料

db dist(point a,point b)

//求兩點之間的距離

int main()

//注意特判

t=n;//中點編號

int pos=0;

db len=1e150;

for(int i=0;iif(po[i].x>sx||po[i].y>sy)no[i]=1;

//不知到為啥還有站在矩陣外的親戚,需要特殊處理剔除掉

db now=dist(po[i],point(bx,by));

if(len>now) len=now,pos=i;

}s=pos;//距離起點最近的那個親戚就是最開始看守它的

for(int i=0;iif(no[i]) continue;

init(i,n);

halfcut(i,vnt);

//建圖啦

}printf("%d\n",spfa(n+2));

//最短路出答案

}return

0;}

注意一下特判和精度就好啦,最討厭卡精度的題,不過這道還好

SDOI2013 刺客信條

故事發生在1486 年的義大利,ezio 原本只是乙個文藝復興時期的貴族,後來因為家族成員受到聖殿騎士的殺害,決心成為一名刺客。最終,憑藉著他的努力和出眾的天賦,成為了傑出的刺客大師,他不僅是個身手敏捷的武林高手,飛簷走壁擅長各種暗殺術。刺客組織在他的帶領下,為被剝削的平民聲張正義,趕跑了原本統治義...

SDOI2013 保護出題人

出題人銘銘認為給sdoi2012 出題太可怕了,因為總要被罵,於是他又給sdoi2013 出題了。參加sdoi2012 的小朋友們釋放出大量的殭屍,企圖攻擊銘銘的家。而你作為sdoi2013的參賽者,你需要保護出題人銘銘。殭屍從唯一一條筆直道路接近,你們需要在銘銘的房門前放置植物攻擊殭屍,避免殭屍碰...

SDOI2013 保護出題人

點此看題 感覺這道題網上講解不是特別清楚,我來補一發詳細講解吧,因為作者也是花了好久才搞懂。首先把題目所求轉化成形式化表達 其中s ss是生命值a aa的字首和 i 1nmax j 1is i s j 1 x i i j d sum n max i frac i 1 n j 1maxi x i i ...