洛谷P4049 [JSOI2007]合金——题解

题目传送门
题目大意:
看题面吧。


思考过程:
首先很显然地一点,第三维是可以忽略的,因为c=1-a-b。
我们从最简单的情况开始考虑,如果只有两种备选合金,能配出的合金就在这两种合金连线的线段上,三种就在三种合金形成的三角形中,以此类推,n种就在这n种合金围成的凸包上。


具体做法:
floyd求最小环,具体的是如果一个点在线段ij的一边,dis[i][j]=1,否则为inf,然后跑floyd就可以了。(注意几种需要特判的情况)


代码:

#include <bits/stdc++.h>
using namespace std;

const int maxn=1100,inf=1000000;
const double eps=1e-6;
struct point
{
    double x,y;
    point operator-(point &s)
    {
        return (point){x-s.x,y-s.y};
    }
}a[maxn],b[maxn];
int dis[maxn][maxn];
int n,m;

double operator*(point a,point b)
{
    return a.x*b.y-b.x*a.y; 
}

bool spj()
{
    for(int i=1;i<=n;i++) if(fabs(a[i].x-a[1].x)>eps||fabs(a[i].y-a[1].y)>eps) return 0;
    for(int i=1;i<=m;i++) if(fabs(b[i].x-a[1].x)>eps||fabs(b[i].y-a[1].y)>eps) return 0;
    printf("1\n");
    return 1;
}   

bool can(point p1,point p2)
{
    if(p1.x>p2.x) swap(p1,p2);
    for(int i=1;i<=m;i++) if(b[i].x<p1.x||b[i].x>p2.x) return 0;
    if(p1.y>p2.y) swap(p1,p2);
    for(int i=1;i<=m;i++) if(b[i].y<p1.y||b[i].y>p2.y) return 0;
    return 1;   
}

int judge(point p1,point p2)
{
    int c1=0,c2=0;
    for(int i=1;i<=m;i++)
    {
        double t=(p2-p1)*(b[i]-p1);
        if(t>eps) c1++;
        if(t<-eps) c2++;
        if(c1*c2) return 0;     
    }
    if(!c1&&!c2&&can(p1,p2)) return -1;
    if(c1) return 1;
    if(c2) return 2;
    return 3;
}

void floyd()
{
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    int ans=inf;
    for(int i=1;i<=n;i++) ans=min(ans,dis[i][i]);
    if(ans==inf||ans<=2) printf("-1\n");
    else printf("%d\n",ans);    
}

void work()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            int flag=judge(a[i],a[j]);
            if(flag==-1) { printf("2\n");return; }
            else if(flag==0) dis[i][j]=inf;
            else if(flag==1) dis[i][j]=1;
            else if(flag==2) dis[j][i]=1;
            else { dis[i][j]=1;dis[j][i]=1; }   
        }
    }
    floyd();
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            dis[i][j]=inf;
    double ttt;
    for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&a[i].x,&a[i].y,&ttt);
    for(int i=1;i<=m;i++) scanf("%lf%lf%lf",&b[i].x,&b[i].y,&ttt);
    if(spj()) return 0;
    work();
    return 0;   
}

猜你喜欢

转载自blog.csdn.net/qq_39662197/article/details/80258269