题目链接:点击打开链接


题解思路:很难想到这是一题图论题。那么我们枚举度度熊和小伙伴任意两个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;
}