P4049 [JSOI2007]合金

传送门

我数学可能白学了……

因为三个数加起来等于\(1\),那么只要用前两个数就能表示,那么就能把每一种金属看成一个二维向量。考虑只有两个向量的时候,设这两个向量为\(a,b\),那么一个向量\(c\)能被表示也就是说存在\(ax+by=c\)且\(x+y=1\),根据数学老师说的那么\(c\)在\(a\)和\(b\)的终点连成的直线上,那么这里因为\(x\)和\(y\)非负所以是在这条线段上。推广一下(我也不知道怎么推广),有\(n\)个向量的时候能表示的范围就在这\(n\)个点的凸包里

于是就转化为求一个合金构成的点数最少的凸包且要完全包住顾客的凸包

那么就枚举所有的点对,如果所有顾客都在\((i,j)\)这条边的同一侧,那么就加入这条边。最后跑一个floyd求最小环

//minamoto
#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define eps 1e-10
using namespace std;
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
const int N=505;
struct node{
    double x,y;
    node(){}
    node(double x,double y):x(x),y(y){}
}p[N],e[N];
double cross(node a,node b,node c){return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);}
inline bool check(node a,node b,node c){return (a.x>c.x&&b.x>c.x)||(a.x<c.x&&b.x<c.x)||(a.y>c.y&&b.y>c.y)||(a.y<c.y&&b.y<c.y);}
int g[N][N];bool flag;double res;int mn=0x3f3f3f3f;
//inline double abs(double x){return x<0?-x:x;}
int main(){
//  freopen("testdata.in","r",stdin);
    int n,m;scanf("%d%d",&m,&n);
    fp(i,1,m)scanf("%lf%lf%lf",&e[i].x,&e[i].y,&res);
    fp(i,1,n)scanf("%lf%lf%lf",&p[i].x,&p[i].y,&res);
    fp(i,1,m){
        flag=true;
        fp(j,1,n)if(abs(e[i].x-p[j].x)>eps||abs(e[i].y-p[j].y)>eps){flag=false;break;}
        if(flag)return puts("1"),0;
    }
    memset(g,0x3f,sizeof(g));
    fp(i,1,m)fp(j,1,m)if(i!=j){
        if(abs(e[i].x-e[j].x<eps)&&abs(e[i].y-e[j].y)<eps)continue;
        flag=true;
        fp(k,1,n)if(cross(e[i],e[j],p[k])<-eps){flag=false;break;}
        if(!flag)continue;
        fp(k,1,n){
            res=cross(e[i],e[j],p[k]);
            if(res<eps&&res>-eps&&check(e[i],e[j],p[k])){flag=false;break;}
        }
        if(flag)g[i][j]=1;
    }
    fp(k,1,m)fp(i,1,m)fp(j,1,m)cmin(g[i][j],g[i][k]+g[k][j]);
    fp(i,1,m)fp(j,1,m)
    cmin(mn,i==j?g[i][j]:g[i][j]+g[j][i]);
    printf("%d\n",mn>m?-1:mn);return 0;
}

原文地址:https://www.cnblogs.com/bztMinamoto/p/9997840.html

时间: 2024-10-12 22:33:05

P4049 [JSOI2007]合金的相关文章

bzoj千题计划123:bzoj1027: [JSOI2007]合金

http://www.lydsy.com/JudgeOnline/problem.php?id=1027 因为x+y+z=1,所以z=1-x-y 第三维可以忽略 将x,y 看做 平面上的点 简化问题: 若只有两种 材料,那么可以合成 两点线段 上的所有的点 推广到多种材料: 若 用户点 在 材料点 构成的 凸包内,则可以合成 所以题目转化为 求材料点 组成的 能包含所有用户点 的 最小环 用Floyd 枚举 每两对材料点,若所有用户点在 在线段的左侧或在线段上 则 f[i][j]=1 表示i到j

bzoj 1027[JSOI2007]合金 - floyd + 凸包

1027: [JSOI2007]合金 Time Limit: 4 Sec  Memory Limit: 162 MB Description 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的合金.新的合金的铁铝锡比重为用户所需要的比重. 现在,用户给出了n种他们需要的合金,以及每种合金中铁铝锡的比重.公司希望能够订购最少种类的原材料,并且使用这些原材料可以加工出用户需要

[BZOJ 1027][JSOI2007]合金(计算几何+Floyd最小环)

Description 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的合金.新的合金的铁铝锡比重为用户所需要的比重. 现在,用户给出了n种他们需要的合金,以及每种合金中铁铝锡的比重.公司希望能够订购最少种类的原材料,并且使用这些原材料可以加工出用户需要的所有种类的合金. Solution 今天考试T3的70分算法似乎是这道原题(然而我没做过QwQ) 思路值得学习一下(

[bzoj1027][JSOI2007]合金

来自FallDream的博客,未经允许,请勿转载,谢谢. 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的合金.新的合金的铁铝锡比重为用户所需要的比重. 现在,用户给出了n种他们需要的合金,以及每种合金中铁铝锡的比重.公司希望能够订购最少种类的原材料,并且使用这些原材料可以加工出用户需要的所有种类的合金. n,m<=500 看到这道神题根本没头绪,只好看看题解. 因为三

【BZOJ】1027: [JSOI2007]合金(凸包+floyd)

http://www.lydsy.com/JudgeOnline/problem.php?id=1027 没special judge wa了一发好蛋疼... 首先这题大概和黑书上的差不多...由于知道任意两种材料就能得到第三种材料的含量,所以可以忽略第三种含量... 首先来看,如果有两种材料,那么能合成的材料一定在这个线段上,证明很简单... 假设材料A和B,要合成材料C,将他们材料的含量放到二维坐标系上(x轴为材料1,y轴为材料2) 假设用了a的A,则用了1-a的B,有 $$\begin{a

BZOJ 1027 JSOI2007 合金 计算几何+Floyd

题目大意:给定一些合金,选择最少的合金,使这些合金能够按比例合成要求的合金 首先这题的想法特别奇异 看这题干怎么会想到计算几何 并且计算几何又怎么会跟Floyd挂边 好强大 首先因为a+b+c=1 所以我们仅仅要得到a和b就可以 c=1-a-b 所以c能够不读入了 然后我们把每种原料抽象成一个点 可知两个点能合成的合金一定在两点连线的线段上 证明:设两个点为(x1,y1)和(x2,y2),新合成的合金为(ax1+bx2,ay2+by2) (a+b=1,a,b>0) 两点连线为(y-y1)/(x-

[bzoj 1027][JSOI2007]合金(解析几何+最小环)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1027 分析: 首先因为一个合金的和为1,所以考虑2个材料合金能否合成一个需求合金的时候,只要考虑前两个值就可以了. 我们如果把这两个值放到平面直角坐标系中,设两个材料合金坐标分别为(x,y)和(m,n),那么易得这两个材料合金可以合成的需求合金对应的点在(x,y)(m,n)两点之间的线段上.(高中数学向量的性质可以证) 那么问题就转化为了:平面上有m个材料合金点,n个需求合金点,要求

[JSOI2007]合金

题目描述 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的合金.新的合金的铁铝锡比重为用户所需要的比重. 现在,用户给出了n种他们需要的合金,以及每种合金中铁铝锡的比重.公司希望能够订购最少种类的原材料,并且使用这些原材料可以加工出用户需要的所有种类的合金. 输入输出格式 输入格式: 第一行两个整数m和n(m, n ≤ 500),分别表示原材料种数和用户需要的合金种数.

bzoj 1027: [JSOI2007]合金

由于总和一定所以看前两个即可,可以他们抽象成平面上的点,两个点能合出来的点在以两点为端点的线段上,三个点的在以三点为顶点的三角形内,... 所以预先处理那两个点的连线在所有被需要的点的一边,便把距离设为1,跑一遍最小环就行了. 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<