好多HDU的題,我想死。
HDU 6325 Problem G. Interstellar Travel
求從左到右字典序最小上凸殼,注意這個題不能選多個重點。
#include<bits/stdc++.h>
#define maxn 200005
#define LL long long
#define Ct const
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;
int n;
#define Pt Point
struct Pt{
LL x,y;
Pt(Ct LL &x=0,Ct LL &y=0):x(x),y(y){}
Pt operator +(Ct Pt &B)Ct{ return Pt(x + B.x , y + B.y); }
Pt operator -(Ct Pt &B)Ct{ return Pt(x - B.x , y - B.y); }
LL operator *(Ct Pt &B)Ct{ return x * B.y - y * B.x; }
}P[maxn];
int c[maxn];
bool cmp(const int &u,const int &v){ return P[u].x == P[v].x ? P[u].y > P[v].y : P[u].x < P[v].x; }
int q[maxn],R;
int main(){
int T;
for(scanf("%d",&T);T--;){
scanf("%d",&n);
rep(i,1,n) scanf("%lld%lld",&P[i].x,&P[i].y),c[i]=i;
stable_sort(c+1,c+1+n,cmp);
q[R=0] = 1;
rep(i,2,n){
int u=c[i];
if(P[u].x == P[c[i-1]].x && P[u].y == P[c[i-1]].y)
continue;
for(;R>=1 && (
(P[q[R]] - P[q[R-1]]) * (P[u] - P[q[R-1]]) > 0
||
((P[q[R]] - P[q[R-1]]) * (P[u] - P[q[R-1]]) == 0 && u < q[R])
)
;)
R--;
q[++R] = u;
}
rep(i,0,R) printf("%d%c",q[i]," \n"[i==R]);
}
}
HDU 2202 最大三角形
求個點中選三個點的最大三角形面積。
首先存在一個最大三角形三個點都在凸包上。
求出凸包後有的旋轉卡殼和的暴力枚舉算法。
但是他們都能過。
這是因爲這道題有一個性質是
設
有一個結論就是凸包上的點數上界是(期望點數是的)
首先很多構造凸包的想法都是的,
證明思路應該是有效的斜率只有種(具體證明應該和有關,也就是和最簡分數有關其實就是我不會),這是答案的上界。
然後這裏給出一個構造:
造一個的圓,把圓內所有頂點造個凸包,容易發現這個凸包的點數就是級別的。
這東西怎麼網上一點提示都沒有啊啊啊啊啊啊啊啊啊連CF出題人都敷衍了事這莫非是什麼離譜的openproblem嗎
#include<bits/stdc++.h>
#define maxn 50005
#define LL long long
#define Ct const
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;
int n;
#define Pt Point
struct Pt{
LL x,y;
Pt(Ct LL &x=0,Ct LL &y=0):x(x),y(y){}
Pt operator +(Ct Pt &B)Ct{ return Pt(x + B.x , y + B.y); }
Pt operator -(Ct Pt &B)Ct{ return Pt(x - B.x , y - B.y); }
LL operator *(Ct Pt &B)Ct{ return x * B.y - y * B.x; }
}P[maxn];
int c[maxn];
bool cmp(const int &u,const int &v){ return P[u].x == P[v].x ? P[u].y > P[v].y : P[u].x < P[v].x; }
int q[maxn],R;
int main(){
//freopen("1.in","r",stdin);
for(;scanf("%d",&n) != EOF;){
rep(i,1,n) scanf("%lld%lld",&P[i].x,&P[i].y),c[i]=i;
stable_sort(c+1,c+1+n,cmp);
q[R=0] = c[1];
rep(i,2,n){
int u=c[i];
for(;R>=1 && ((P[q[R]] - P[q[R-1]]) * (P[u] - P[q[R-1]]) >= 0);)R--;
q[++R] = u;
}
int L = R;
per(i,n,1){
int u = c[i];
for(;R>L && ((P[q[R]] - P[q[R-1]]) * (P[u] - P[q[R-1]]) >= 0);)R--;
q[++R] = u;
}
LL ans = 0;
rep(i,0,R) rep(j,i+1,R) rep(k,j+1,R)
ans = max(ans , abs((P[q[j]]-P[q[i]]) * (P[q[k]]-P[q[i]])));
printf("%.2lf\n",(double)ans / 2);
}
}
HDU 1392 Surround the Trees
垃圾題目,題意有病,建議出題人審視一下自己的conscience
#include<bits/stdc++.h>
#define maxn 50005
#define LL long long
#define Ct const
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;
int n;
double sqr(double a){ return a * a; }
#define Pt Point
struct Pt{
LL x,y;
Pt(Ct LL &x=0,Ct LL &y=0):x(x),y(y){}
Pt operator +(Ct Pt &B)Ct{ return Pt(x + B.x , y + B.y); }
Pt operator -(Ct Pt &B)Ct{ return Pt(x - B.x , y - B.y); }
LL operator *(Ct Pt &B)Ct{ return x * B.y - y * B.x; }
double dist(Ct Pt &B)Ct{
return sqrt(sqr(x - B.x) + sqr(y - B.y));
}
}P[maxn];
int c[maxn];
bool cmp(const int &u,const int &v){ return P[u].x == P[v].x ? P[u].y > P[v].y : P[u].x < P[v].x; }
int q[maxn],R;
int main(){
//freopen("1.in","r",stdin);
for(;scanf("%d",&n) != EOF && n;){
rep(i,1,n) scanf("%lld%lld",&P[i].x,&P[i].y),c[i]=i;
stable_sort(c+1,c+1+n,cmp);
q[R=0] = c[1];
rep(i,2,n){
int u=c[i];
for(;R>=1 && ((P[q[R]] - P[q[R-1]]) * (P[u] - P[q[R-1]]) >= 0);)R--;
q[++R] = u;
}
int L = R;
per(i,n,1){
int u = c[i];
for(;R>L && ((P[q[R]] - P[q[R-1]]) * (P[u] - P[q[R-1]]) >= 0);)R--;
q[++R] = u;
}
double ans = 0;
rep(i,0,R-1) ans += P[q[i]].dist(P[q[i+1]]);
if(n == 2) ans /= 2;
printf("%.2lf\n",ans);
}
}
HDU 1469 Video Surveillance
求多邊形的核。
注意到Thus the edges alternate between horizontal and vertical.
所以爲什麼要寫半平面交呢?
#include<cstdio>
#include<algorithm>
#define maxn 105
#define inf 0x3f3f3f3f
using namespace std;
int n,x[maxn],y[maxn],mnx,mxx,mny,mxy;
int main(){
int cas = 0;
while(~scanf("%d",&n) && n){
for(int i=0;i<n;i++) scanf("%d%d",&x[i],&y[i]);
mnx = mny = -inf;
mxx = mxy = inf;
for(int i=0;i<n;i++){
int v = (i+1)%n;
if(x[i] == x[v]){
if(y[i] > y[v]) mxx = min(mxx , x[i]);
else mnx = max(mnx , x[i]);
}
else{
if(x[i] < x[v]) mxy = min(mxy , y[i]);
else mny = max(mny , y[i]);
}
}
printf("Floor #%d\n",++cas);
if(mnx > mxx || mny > mxy) puts("Surveillance is impossible.");
else puts("Surveillance is possible.");
putchar('\n');
}
}
HDU 5462 Manors
個人,每個人有個旗子座標爲,求在 的土地上每一個點按照計算的最小的那個就是這個位置的主人,求每個人的土地大小。
半平面交即可得到面積。
#include<bits/stdc++.h>
#define db double
#define Ct const
#define Pt Point
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define eps 1e-8
#define maxn 205
#define maxm 2005
using namespace std;
int n,m;
db x[maxn][maxm] , y[maxn][maxm] , smx[maxn] , smy[maxn] , smx2[maxn] , smy2[maxn];
int dcmp(Ct db &a){ return a < -eps ? -1 : a > eps ? 1 : 0; }
db sqr(Ct db &a){ return a * a; }
struct Pt{
db x,y;
Pt(Ct db &x=0,Ct db &y=0):x(x),y(y){}
Pt operator +(Ct Pt &B)Ct{ return Pt(x+B.x,y+B.y); }
Pt operator -(Ct Pt &B)Ct{ return Pt(x-B.x,y-B.y); }
db operator *(Ct Pt &B)Ct{ return x * B.y - y * B.x; }
Pt operator *(Ct db &B)Ct{ return Pt(x * B , y * B); }
}qp[maxn];
struct Ln{
Pt S,T;
db ang;
Ln(Ct Pt &S=0,Ct Pt &T=0):S(S),T(T){ ang = atan2(T.y-S.y,T.x-S.x); }
bool operator <(Ct Ln &B)Ct{ return dcmp(ang - B.ang) ? ang < B.ang : (B.T - S) * (T - S) < 0; }
}L[maxn],q[maxn];
int cnt,ql,qr;
Pt Itp(Ct Pt &p1,Ct Pt &v1,Ct Pt &p2,Ct Pt &v2){ return p1 + v1 * ((p2 - p1) * v2 / (v1 * v2)); }
#define Ptln(a) a.S,a.T-a.S
db HalfPlaneInsection(){
sort(L+1,L+1+cnt);
ql=0,qr=-1;
rep(i,1,cnt) if(i == 1 || dcmp(L[i].ang - L[i-1].ang)){
for(;ql<=qr-1 && (qp[qr] - L[i].S) * (L[i].T - L[i].S) <= 0;qr--);
for(;ql<=qr-1 && (qp[ql+1] - L[i].S) * (L[i].T - L[i].S) <= 0;ql++);
q[++qr] = L[i];
if(ql<=qr-1) qp[qr] = Itp(Ptln(q[qr]),Ptln(q[qr-1]));
}
for(;ql<=qr-2 && (qp[qr] - q[ql].S) * (q[ql].T - q[ql].S) <= 0;qr--);
if(qr-ql<2) return 0;
qp[ql] = Itp(Ptln(q[qr]),Ptln(q[ql]));
db ans = 0;
rep(i,ql,qr){
int v = i + 1;
if(v > qr) v = ql;
ans += (qp[i] - qp[ql]) * (qp[v] - qp[ql]);
}
return ans / 2;
}
int main(){
int T,cas=0;
for(scanf("%d",&T);T--;){
scanf("%d%d",&n,&m);
rep(i,1,n) smx[i] = smy[i] = smx2[i] = smy2[i] = 0;
rep(i,1,n) rep(j,1,m) scanf("%lf%lf",&x[i][j],&y[i][j]) , smx[i] += x[i][j] , smx2[i] += sqr(x[i][j]) , smy[i] += y[i][j] , smy2[i] += sqr(y[i][j]);
printf("Case #%d: ",++cas);
rep(i,1,n){
cnt = 0;
rep(j,1,n) if(i^j){
db A=2 * (smx[j] - smx[i]),B=2 * (smy[j] - smy[i]),C=smx2[i] + smy2[i] - smx2[j] - smy2[j];
Pt S , T;
if(dcmp(A)) S = Pt(- C / A , 0);
else S = Pt(0 , -C / B);
T = S + Pt(B,-A);
L[++cnt] = Ln(S,T);
}
L[++cnt] = Ln(Pt(0,0) , Pt(0,4095));
L[++cnt] = Ln(Pt(0,4095) , Pt(4095,4095));
L[++cnt] = Ln(Pt(4095,4095),Pt(4095,0));
L[++cnt] = Ln(Pt(4095,0),Pt(0,0));
printf("%d%c",(int)round(HalfPlaneInsection())," \n"[i==n]);
}
}
}
HDU 4327 Shooting
在的平面內每個點有個權重,平面內有個點,現在在平面上帶權隨機選擇一個點,問離這個點最近的點是的概率。
和上題基本一樣,半平面交求出每個點的範圍後求積分:
假如是,求線段下的帶權積分。
形式不太優美,設
原式分成三部分:
然後就硬算即可。
#include<bits/stdc++.h>
#define db double
#define Ct const
#define Pt Point
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define eps 1e-8
#define maxn 205
#define maxm 2005
using namespace std;
int n,m;
db x[maxn],y[maxn];
int dcmp(Ct db &a){ return a < -eps ? -1 : a > eps ? 1 : 0; }
db sqr(Ct db &a){ return a * a; }
db cube(Ct db &a){ return a * a * a; }
struct Pt{
db x,y;
Pt(Ct db &x=0,Ct db &y=0):x(x),y(y){}
Pt operator +(Ct Pt &B)Ct{ return Pt(x+B.x,y+B.y); }
Pt operator -(Ct Pt &B)Ct{ return Pt(x-B.x,y-B.y); }
db operator *(Ct Pt &B)Ct{ return x * B.y - y * B.x; }
Pt operator *(Ct db &B)Ct{ return Pt(x * B , y * B); }
}qp[maxn];
struct Ln{
Pt S,T;
db ang;
Ln(Ct Pt &S=0,Ct Pt &T=0):S(S),T(T){ ang = atan2(T.y-S.y,T.x-S.x); }
bool operator <(Ct Ln &B)Ct{ return dcmp(ang - B.ang) ? ang < B.ang : (B.T - S) * (T - S) < 0; }
}L[maxn],q[maxn];
int cnt,ql,qr;
Pt Itp(Ct Pt &p1,Ct Pt &v1,Ct Pt &p2,Ct Pt &v2){ return p1 + v1 * ((p2 - p1) * v2 / (v1 * v2)); }
#define Ptln(a) a.S,a.T-a.S
db HalfPlaneInsection(){
sort(L+1,L+1+cnt);
ql=0,qr=-1;
rep(i,1,cnt) if(i == 1 || dcmp(L[i].ang - L[i-1].ang)){
for(;ql<=qr-1 && (qp[qr] - L[i].S) * (L[i].T - L[i].S) <= 0;qr--);
for(;ql<=qr-1 && (qp[ql+1] - L[i].S) * (L[i].T - L[i].S) <= 0;ql++);
q[++qr] = L[i];
if(ql<=qr-1) qp[qr] = Itp(Ptln(q[qr]),Ptln(q[qr-1]));
}
for(;ql<=qr-2 && (qp[qr] - q[ql].S) * (q[ql].T - q[ql].S) <= 0;qr--);
if(qr-ql<2) return 0;
qp[ql] = Itp(Ptln(q[qr]),Ptln(q[ql]));
db ans = 0;
rep(i,ql,qr){
int v = i + 1;
if(v > qr) v = ql;
if(dcmp(qp[i].x - qp[v].x)){
db K = (qp[v].y - qp[i].y) / (qp[v].x - qp[i].x) , B = qp[i].y - qp[i].x * K;
ans += (qp[v].x - qp[i].x) * (qp[v].y + qp[i].y)
+ K * (cube(qp[i].x) - cube(qp[v].x)) / 3
+ B * (sqr(qp[i].x) - sqr(qp[v].x)) / 2
+ sqr(K) * (cube(qp[i].x) - cube(qp[v].x)) / 6
+ sqr(B) * (qp[i].x - qp[v].x) / 2
+ K * B * (sqr(qp[i].x) - sqr(qp[v].x)) / 2;
}
}
return fabs(ans);
}
int main(){
int T,cas=0;
for(scanf("%d",&T);T--;){
scanf("%d",&n);
rep(i,1,n) scanf("%lf%lf",&x[i],&y[i]);
printf("Case #%d:\n",++cas);
rep(i,1,n){
cnt = 0;
rep(j,1,n) if(i^j){
db A=2 * (x[j] - x[i]),B=2 * (y[j] - y[i]),C=sqr(x[i]) + sqr(y[i]) - sqr(x[j]) - sqr(y[j]);
Pt S , T;
if(dcmp(A)) S = Pt(- C / A , 0);
else S = Pt(0 , -C / B);
T = S + Pt(B,-A);
L[++cnt] = Ln(S,T);
}
L[++cnt] = Ln(Pt(0,0) , Pt(0,1));
L[++cnt] = Ln(Pt(0,1) , Pt(1,1));
L[++cnt] = Ln(Pt(1,1),Pt(1,0));
L[++cnt] = Ln(Pt(1,0),Pt(0,0));
printf("%.6lf\n",HalfPlaneInsection());
}
}
}
HDU 6354 Everything Has Changed
用一堆圓來切割一個圓心爲原點,半徑爲R的圓A,問切割完畢後圓A外圍剩餘部分的周長。
注意到題目中所有圓都只會和大圓相交,所以直接判斷相交後加入大圓被刪去的部分加回小圓加入的部分。
#include<bits/stdc++.h>
#define db double
#define Pi 3.1415926535897932384626433832795
using namespace std;
int m;
db R,x,y,r;
db sqr(db a){ return a * a; }
int main(){
int T;
scanf("%d",&T);
for(;T--;){
scanf("%d%lf",&m,&R);
db ans = 2 * Pi * R;
for(int i=1;i<=m;i++){
scanf("%lf%lf%lf",&x,&y,&r);
db d = sqrt(x*x+y*y);
if(d + r >= R && d - r <= R){
db a = acos((sqr(d) + sqr(R) - sqr(r)) / d / 2 / R);
db b = acos((sqr(d) + sqr(r) - sqr(R)) / d / 2 / r);
ans += b * 2 * r - a * 2 * R;
}
}
printf("%.15lf\n",ans);
}
}