码迷,mamicode.com
首页 > Web开发 > 详细

bzoj 1027: [JSOI2007]合金【凸包+Floyd】

时间:2018-03-09 22:43:21      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:情况   bool   iostream   多个   最小   struct   一点   std   mat   

参考:https://www.cnblogs.com/zhuohan123/p/3237246.html
因为一c可以由1-a-b得出,所以删掉c,把a,b抽象成二维平面上的点。首先考虑一个客户需求能被哪些原料配出来:两个原料点连线上的点都可以,要是多个原料点,那么这些线的向量构成的凸包中的点都可以
所以得到了一个n三方算法:枚举每两个原料点,看是否所有需求点都在这条向量的半平面里,是则连1,然后Floyd求最小环即可
但是有非常多恶心的特判……
1.需求点重合为一点
2.需求点出现在两种原料点所在直线上的情况

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int N=505,inf=1e9;
const double eps=1e-10;
int m,n,a[N][N];
double c;
struct dian
{
    double x,y;
    dian(double X=0,double Y=0)
    {
        x=X,y=Y;
    }
    dian operator - (const dian &a) const
    {
        return dian(x-a.x,y-a.y);
    }
}q[510],p[510];
dian V(dian a,dian b)
{
    return dian(b.x-a.x,b.y-a.y);
}
double cj(dian a,dian b)
{
    return a.x*b.y-b.x*a.y;
}
bool ok(dian s,dian t,dian p)
{
    return !((s.x>p.x&&t.x>p.x)||(s.x<p.x&&t.x<p.x)||(s.y>p.y&&t.y>p.y)||(s.y<p.y&&t.y<p.y));
}
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++)
        scanf("%lf%lf%lf",&p[i].x,&p[i].y,&c);
    for(int i=1;i<=n;i++)
        scanf("%lf%lf%lf",&q[i].x,&q[i].y,&c);
    for(int i=1;i<=m;i++)
    {
        bool flag=1;
        for(int j=1;j<=n;j++)
            if(abs(p[i].x-q[j].x)>eps||abs(p[i].y-q[j].y)>eps)
                flag=0;
        if(flag)
        {
            printf("1\n");
            return 0;
        }
    }
    for(int i=1;i<=m;i++)
        for(int j=1;j<=m;j++)
            a[i][j]=inf;
    for(int i=1;i<=m;i++)
        for(int j=1;j<=m;j++)
        if(i!=j)
        {
            if(abs(p[i].x-p[j].x)<eps&&abs(p[i].y-p[j].y)<eps)
                continue ;  
            int can=1;
            for(int k=1;k<=n;k++)
                if(cj(p[j]-p[i],q[k]-p[i])<-eps)
                    can=0;
            if(can)
            {
                for(int k=1;k<=n;k++)
                {
                    double cp=cj(p[j]-p[i],q[k]-p[i]);
                    if(cp<eps&&cp>-eps&&(!ok(p[i],p[j],q[k])))
                        can=0;
                }
            }
            if(can)
                a[i][j]=1;
        }
    int ans=inf;
    for(int k=1;k<=m;k++)
        for(int i=1;i<=m;i++)
            for(int j=1;j<=m;j++)
                if(a[i][j]>a[i][k]+a[k][j])
                    a[i][j]=a[i][k]+a[k][j];
    for(int i=1;i<=m;i++)
        for(int j=1;j<=m;j++)
        {
            if(i!=j&&a[i][j]+a[j][i]<ans)
                ans=a[i][j]+a[j][i];
            if(i==j&&a[i][j]<ans)
                ans=a[i][j];
        }
    printf("%d\n",ans==inf?-1:ans);
    return 0;
}

bzoj 1027: [JSOI2007]合金【凸包+Floyd】

标签:情况   bool   iostream   多个   最小   struct   一点   std   mat   

原文地址:https://www.cnblogs.com/lokiii/p/8536447.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!