度度熊保护村庄 HDU - 6080 floyd最小环/叉积判左右
点在向量同侧的话就把向量的两个点连一条路,最后跑一次floyd求到自己的最小环
不知道为什么500^3跑得飞快
#include<bits/stdc++.h> #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) const int inf=0x3f3f3f3f; const int maxn=1e6+9; const int mod=1e9+7; struct Point{ int x,y; Point operator -(const Point &b)const{ Point c;c.x=x-b.x;c.y=y-b.y;return c; } double operator *(const Point &b)const{ return x*b.y-y*b.x; } }; Point h[505],s[505]; int n,m,ans,G[505][505]; inline bool judge(Point x,Point y,Point z){ if((x.x<z.x&&y.x<z.x)||(x.y<z.y&&y.y<z.y)||(x.x>z.x&&y.x>z.x)|| (x.y>z.y&&y.y>z.y))return 1; return 0; } int main(){ while(~scanf("%d",&n)){ memset(G,0x3f,sizeof G); for(int i=1;i<=n;i++)scanf("%d%d",&h[i].x,&h[i].y); scanf("%d",&m); FOR(m)scanf("%d%d",&s[i].x,&s[i].y); int flag; FOR(m){ for(int j=1;j<=m;j++){ flag=1; for(int k=1;k<=n;k++){ if((s[i]-s[j])*(s[i]-h[k])<0|| (s[i]-s[j])*(s[i]-h[k])==0&&judge(s[i],s[j],h[k])){ //右侧或延长线上 flag=0;break; } } if(flag){ G[i][j]=1; } } } ans=inf; for(int k=1;k<=m;k++){ for(int i=1;i<=m;i++){ if(G[i][k]==inf)continue; for(int j=1;j<=m;j++)G[i][j]=min(G[i][j],G[i][k]+G[k][j]); } } for(int i=1;i<=m;i++)ans=min(ans,G[i][i]); if(ans>m)printf("ToT\n"); else printf("%d\n",m-ans); } }