题目链接:点击打开链接
题解思路:很难想到这是一题图论题。那么我们枚举度度熊和小伙伴任意两个ab组成一个线段看n个村庄是否都在他右边则将ab连接,如果在右边就连接ba,如果都在线段上就双向连接,然后用floyed求最小环。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
const int mx = 5e2+5,mod = 1e9+7;
int n,m,d[mx][mx];
struct node{
double x,y;
}s1[mx],s2[mx];
int dire(int p1,int p2,int p){
int ans = (s1[p].x - s2[p2].x) * (s2[p1].y - s2[p2].y) - (s2[p1].x - s2[p2].x) * (s1[p].y -s2[p2].y);
if(ans==0) return 0;
if(ans>0) return 1;
return 2;
}
int main(){
while(~scanf("%d",&n)){
memset(d,inf,sizeof(d));
for(int i=1;i<=n;i++) scanf("%lf%lf",&s1[i].x,&s1[i].y);
scanf("%d",&m);
for(int i=1;i<=m;i++) scanf("%lf%lf",&s2[i].x,&s2[i].y);
for(int i=1;i<=m;i++){
for(int j=i+1;j<=m;j++){
int flag = 0,flag1 = 3;
for(int k=1;k<=n;k++){
int val = dire(i,j,k);
if(!val){
if(min(s2[i].x,s2[j].x)<=s1[k].x&&max(s2[i].x,s2[j].x)>=s1[k].x) continue;
flag = 1;
break;
}
if(flag1==3) flag1 = val;
else{
if(flag1!=val){
flag = 1;
break;
}
}
}
if(!flag){
if(flag1==1||flag1==3) d[j][i] = 1;
if(flag1==2||flag1==3) d[i][j] = 1;
}
}
}
for(int k=1;k<=m;k++)
for(int i=1;i<=m;i++){
if(d[i][k]==inf) continue;
for(int j=1;j<=m;j++)
d[i][j] = min(d[i][j],d[i][k]+d[k][j]);
}
int ans = inf;
for(int i=1;i<=m;i++)
ans = min(ans,d[i][i]);
if(ans==inf) puts("ToT");
else printf("%d\n",m-ans);
}
return 0;
}