您的位置:首页 > 大数据 > 人工智能

2018 BUPT Winter Training #6 Div.2

2018-03-07 22:52 363 查看

A - Intersecting Lines

rt,求相交直线。

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
using namespace std;
const double eps = 1e-6;
struct Point {
double x,y;
Point(){}
Point(double _x,double _y){x = _x;y = _y;}
Point get(){cin>>x>>y;return Point(x,y);}
Point operator+(const Point &b)const{return Point(x+b.x,y+b.y);}
Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
double operator*(const Point &b)const{return x*b.x+y*b.y;}
double operator^(const Point &b)const {return x*b.y-y*b.x;}
}P[5];
int main(void) {
int T,t;
cin>>T;
cout<<"INTERSECTING LINES OUTPUT\n";
while(T--){
FF(i,1,4)P[i].get();
if(fabs((P[2]-P[1])^(P[4]-P[3]))<eps){
if(fabs((P[3]-P[1])^(P[4]-P[1]))<eps)cout<<"LINE"<<endl;
else cout<<"NONE"<<endl;
}else{
double a1=P[1].y-P[2].y,a2=P[3].y-P[4].y;
double b1=P[2].x-P[1].x,b2=P[4].x-P[3].x;
double c1=P[1]^P[2],c2=P[3]^P[4];
double D=a1*b2-a2*b1;
cout<<fixed<<"POINT "<<setprecision(2)<<(b1*c2-b2*c1)/D<<" "<<(a2*c1-a1*c2)/D<<endl;
}
}
cout<<"END OF OUTPUT\n";
}


B - The Doors

暴力枚举线段相交…这就很不优美了。

#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <utility>
#include <queue>
#include <iomanip>
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
#define TRV(_i,_V) for(int _i=(_V).size()-1;_i+1;_i--)
#define PB push_back
#define all(x) x.begin(),x.end()
#define MP make_pair
#define sec second
#define fir first
using namespace std;

const double eps=1e-7;
int sgn(double x){
return (fabs(x)>=eps)*x;
}
struct Point {
double x,y;
Point(){}
Point(double _x,double _y){x=_x;y=_y;}
Point get(){cin>>x>>y;return Point(x,y);}
Point operator+(const Point &b)const{return Point(x+b.x,y+b.y);}
Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
double operator*(const Point &b)const{return x*b.x+y*b.y;}
double operator^(const Point &b)const {return x*b.y-y*b.x;}
};
struct Line {
Point a,b;
Line(){}
Line(Point _a,Point _b){a=_a;b=_b;}
};
typedef pair<double,Line> W;
vector<int> ade[150];
vector<W> wall;
vector<Point> P;
inline double dis(int x,int y){return sqrt((P[x].x-P[y].x)*(P[x].x-P[y].x)+(P[x].y-P[y].y)*(P[x].y-P[y].y));}
inline bool SegCross(Line a,Line b){
return ((a.a-b.a)^(a.b-b.a))*((a.a-b.b)^(a.b-b.b))<0&&((b.a-a.a)^(b.b-a.a))*((b.a-a.b)^(b.b-a.b))<0;
}
bool check(int x,int y){
Line l=Line(P[x],P[y]);
double m;
TRV(w,wall){
if(P[x].x<=wall[w].fir&&wall[w].fir<=P[y].x&&SegCross(l,wall[w].sec))return 0;
}
return 1;
}
typedef pair<double,int> pdi;
bool vis[120];
int main(){
pdi t;int n,e;double x,y1,y2,y3,y4;Point start=Point(0,5),end=Point(10,5);
ios::sync_with_stdio(false);
while(cin>>n&&n!=-1){
P.clear();wall.clear();
F(i,(n<<2)+10)ade[i].clear();
memset(vis,0,sizeof(vis));
priority_queue<pdi,vector<pdi>,greater<pdi> > q;

P.PB(start);
F(i,n){
cin>>x>>y1>>y2>>y3>>y4;
P.PB(Point(x,y1));
P.PB(Point(x,y2));
P.PB(Point(x,y3));
P.PB(Point(x,y4));
e=(i<<2)+1;
wall.PB(MP(x,Line(Point(x,0),P[e])));
wall.PB(MP(x,Line(P[e+1],P[e+2])));
wall.PB(MP(x,Line(P[e+3],Point(x,10))));
}
e=P.size();
P.PB(end);
TRV(i,P)F(j,i)if(check(j,i))ade[j].PB(i);
q.push(MP(0,0));
while(!q.empty()){
t=q.top();q.pop();
if(vis[t.sec])continue;
vis[t.sec]=1;
if(t.sec==e)break;
TRV(i,ade[t.sec])q.push(MP(t.fir+dis(t.sec,ade[t.sec][i]),ade[t.sec][i]));
}
cout<<fixed<<setprecision(2)<<t.fir<<endl;
}
}


C - Space Ant

求连接点最多的螺旋线,用极角排序就ok了。

#include <iostream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iomanip>
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
using namespace std;
const double eps=1e-8;
inline double sgn(double x){return (fabs(x)>=eps)*x;}
struct Point {
double x,y;
int id;
Point(){}
Point(double _x,double _y,int _id=0){id=_id;x = _x;y = _y;}
Point get(){cin>>id>>x>>y;return Point(x,y,id);}
bool operator<(const Point &b)const{return y<b.y||(y==b.y&&x<b.x);}
Point operator+(const Point &b)const{return Point(x+b.x,y+b.y);}
Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
double operator*(const Point &b)const{return x*b.x+y*b.y;}
double operator^(const Point &b)const {return x*b.y-y*b.x;}
}P[105];
//inline double dis(int x,int y){return sqrt((P[x]-P[y])*(P[x]-P[y]));}
//inline double dis(int x,int y){return (P[x]-P[y])*(P[x]-P[y]);}
//inline double dis(Point x,Point y){return sqrt((x-y)*(x-y));}
inline double dis(Point x,Point y){return (x-y)*(x-y);}
int cur;
bool cmp(Point x,Point y){
double t=sgn((x-P[cur])^(y-P[cur]));
return t==0&&dis(x,P[cur])<dis(y,P[cur])||t>0;
}
int main(){
int T,n;
ios::sync_with_stdio(false);
P[0]=Point(0,0);
for(cin>>T;T--;){
cin>>n;
FF(i,1,n){
P[i].get();
if(P[i]<P[1])swap(P[1],P[i]);
}
cur=1;
cout<<n<<" "<<P[1].id;
FF(i,2,n){sort(P+i,P+n+1,cmp);cout<<" "<<P[cur=i].id;}
cout<<endl;
}
}


D…阵亡

E - Grandpa’s Estate

因为已经是个凸包了,所以不需要判凸包。极角排序后判断同一个边上是否至少有三个点即可。坑爹的是,这道题我WA6次,原因是”YES”“NO”写成了”Yes”“No”…真是破坏了我补div2#6的心情…所以我才没怎么补这次比赛的题了..有时间再把没过的题好好过一遍吧。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
using namespace std;
const double eps=1e-7;
double sgn(double x){
return (fabs(x)>=eps)*x;
}
struct Point {
double x,y;
Point(){}
Point(double _x,double _y){x = _x;y = _y;}
Point operator+(const Point &b)const{return Point(x+b.x,y+b.y);}
Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
double operator*(const Point &b)const{return x*b.x+y*b.y;}
double operator^(const Point &b)const {return x*b.y-y*b.x;}
bool operator==(const Point &b)const{return x==b.x&&y==b.y;}
}P[1005],X;
inline double dis(Point x,Point y){return sqrt((x-y)*(x-y));}
bool cmp(Point x,Point y){
double f=(x-X)^(y-X);
if(f>0)return 1;
if(f==0&&dis(x,X)<dis(y,X))return 1;
return 0;
}
bool Judge(int n){
int curr=0;
bool FIND=0,JUDGE=0;
Point Vec,pre;
for(;;){
if(curr==n)return 1;
Vec=P[curr+1]-P[curr];
if(FIND&&(pre^Vec)==0){
pre=Vec;curr++;continue;
}else FIND=0;
if(JUDGE)if((pre^Vec)!=0)return 0;else FIND=1,JUDGE=0;
else JUDGE=1;
pre=Vec;curr++;
}
}
int main(){
int T,n;
for(scanf("%d",&T);T--;){
scanf("%d",&n);
memset(P,0,sizeof(P));
F(i,n){
scanf("%lf%lf",&P[i].x,&P[i].y);
if(P[i].y<P[0].y||P[i].y==P[0].y&&P[i].x<P[0].x)swap(P[0],P[i]);
}
X=P[0];
sort(P,P+n,cmp);
P
=P[0];
if(n<6){puts("NO");continue;}
if(((P
-P[n-1])^(P[n-1]-P[n-2]))!=0){puts("NO");continue;}
X=P[n-1];
while(((P
-P[n-1])^(P[n-1]-P[n-2]))==0)n--;
n--;P
=X;
puts(Judge(n)?"YES":"NO");
}
}


F..先算了

G - Circle and Points

3200ms:思路是枚举所有可能的圆。

1400ms:因为单位圆的半径是1,判断不需要sqrt,这样效率就大幅升高了。

1200ms:增加离散化评价,如果求得圆心周围九个格子的点还不如ans,就不需要判断了。

//3200ms
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define eps 1e-8
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
using namespace std;
struct Point {
double x,y;
Point(){}
Point(double _x,double _y){x = _x;y = _y;}
Point operator+(const Point &b)const{return Point(x+b.x,y+b.y);}
Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
Point operator/(const double k)const{return Point(x/k,y/k);}
double operator*(const Point &b)const{return x*b.x+y*b.y;}
double operator^(const Point &b)const {return x*b.y-y*b.x;}
bool operator==(const Point &b)const{return x==b.x&&y==b.y;}
bool operator<(const Point &b)const{return x<b.x||x==b.x&&y<b.y;}
}P[305];
inline double dis(Point x,Point y){return sqrt((x-y)*(x-y));}
//1400ms:用下面dis2函数代替dis判断
//inline double dis2(Point x,Point y){return (x-y)*(x-y);}
void getmid(Point P1,Point P2,Point ¢er) {
Point mid;
mid.x=(P1.x+P2.x)/2.0;
mid.y=(P1.y+P2.y)/2.0;
double angle=atan2(P1.x-P2.x,P2.y-P1.y);
double dcm=sqrt(1-dis(P1,mid)*dis(P1,mid));
center.x=mid.x+dcm*cos(angle);
center.y=mid.y+dcm*sin(angle);
}
int main() {
int n,i,j,k;
while(scanf("%d",&n),n){
F(i,n)scanf("%lf%lf",&P[i].x,&P[i].y);
int ans=1;
F(i,n){
for(j=i+1; j<n; ++j) {
if(dis(P[i],P[j])>2.0)continue;
Point center;
getmid(P[i],P[j],center);
int cnt=0;
F(k,n){
if(fabs(P[k].x-center.x)>1||fabs(P[k].y-center.y)>1)continue;
if(dis(P[k],center)<1.0+eps)cnt++;
}
if(ans<cnt)ans=cnt;
}
}
printf("%d\n",ans);
}
return 0;
}


//1200ms
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include <map>
#include<algorithm>
#define eps 1e-8
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
using namespace std;
struct Point {
double x,y;
Point(){}
Point(double _x,double _y){x = _x;y = _y;}
Point operator+(const Point &b)const{return Point(x+b.x,y+b.y);}
Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
Point operator/(const double k)const{return Point(x/k,y/k);}
double operator*(const Point &b)const{return x*b.x+y*b.y;}
double operator^(const Point &b)const {return x*b.y-y*b.x;}
bool operator==(const Point &b)const{return x==b.x&&y==b.y;}
bool operator<(const Point &b)const{return x<b.x||x==b.x&&y<b.y;}
}A[305];
int conj[12][12];
inline double dis(Point x,Point y){return sqrt((x-y)*(x-y));}
inline double dis2(Point x,Point y){return (x-y)*(x-y);}
void getmid(Point P1,Point P2,Point ¢er) {
Point mid;
mid.x=(P1.x+P2.x)/2.0;
mid.y=(P1.y+P2.y)/2.0;
double angle=atan2(P1.x-P2.x,P2.y-P1.y);
double dcm=sqrt(1-dis(P1,mid)*dis(P1,mid));
center.x=mid.x+dcm*cos(angle);
center.y=mid.y+dcm*sin(angle);
}
int main() {
int n,i,j,k,ttt;
while(scanf("%d",&n),n){
memset(conj,0,sizeof(conj));
F(i,n){
scanf("%lf%lf",&A[i].x,&A[i].y);
conj[(int)A[i].x+1][(int)A[i].y+1]++;
}
int ans=1,x,y;
F(i,n){
for(j=i+1; j<n; ++j) {
if(dis(A[i],A[j])>2.0)continue;
Point center;
getmid(A[i],A[j],center);
x=(int)(center.x);y=(int)(center.y);
if(conj[x+1][y+1]+conj[x][y]+conj[x][y+1]+conj[x][y+2]+conj[x+1][y]+conj[x+1][y+2]+conj[x+2][y]+conj[x+2][y+1]+conj[x+2][y+2]<ans)continue;
int cnt=0;
F(k,n){
if(dis2(A[k],center)<1.0+eps)cnt++;
}
if(ans<cnt)ans=cnt;
}
}
printf("%d\n",ans);
}
return 0;
}


H题。。。看pdf蛋疼,先不补了。

I - Disks

那些对向右扩展没有贡献的圆就是答案了。

#include <cstdio>
#include <cmath>
#include <cstring>
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
using namespace std;
double R[1005],Local[1005];
int anss[1005],adj[1005]={0};
int main(){
memset(adj,-1,sizeof(adj));
int n,ans=0,ar=0;double r=0,dis,r2,r1;
Local[0]=R[0]=0;
scanf("%d",&n);
FF(i,1,n)scanf("%lf",&R[i]);
FF(i,1,n){
Local[i]=R[i];
FF(j,1,i-1){
r1=R[j];r2=R[i];if(r1<r2)r1=R[i],r2=R[j];
dis=sqrt((r1+r2)*(r1+r2)-(r1-r2)*(r1-r2))+Local[j];
if(Local[i]<dis){
Local[i]=dis;
adj[i]=j;
}
}
if(r<Local[i]+R[i])r=Local[ar=i]+R[i];
}
for(int i=n;i>ar;i--)anss[ans++]=i;
for(int i=ar;i>0;i=adj[i]){
ar=i-1;
while(ar>0&&ar>adj[i])anss[ans++]=ar--;
}
printf("%d\n",ans);
for(int i=ans-1;i+1;i--)printf("%d\n",anss[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: