Description

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

Input

第一行两个整数m和n(m, n ≤ 500),分别表示原材料种数和用户需要的合金种数。第2到m + 1行,每行三个实数a, b, c(a, b, c ≥ 0 且 a + b + c = 1),分别表示铁铝锡在一种原材料中所占的比重。第m + 2到m + n + 1行,每行三个实数a, b, c(a, b, c ≥ 0 且 a + b + c = 1),分别表示铁铝锡在一种用户需要的合金中所占的比重。

Output

一个整数,表示最少需要的原材料种数。若无解,则输出–1。

Sample Input

3 2
0.25 0.25 0.5
0 0.6 0.5
1 0 0
0.7 0.1 0.2
0.85 0.05 0.1

Sample Output

2

HINT

 

Source

首先可以知道第三个比例是吃翔的(明显啊,1-前面两个就是第三个)。其次,我们再说一个结论:将合金的第一个比例看做x,第二个看做y,则n种合金所能形成的所有合金就是在这n种合金的凸包中(凸包的经典应用)。

因此,问题转换为对目标点求凸包,在从给定点中找出一个闭包将目标凸包包裹起来。问题再一次转换,对于所有合法的边,我们要求的就是一个边权最小的环,就是求floyed求最小环。

好,那么问题就来了。怎么连边呢,首先边不能穿过凸包,还有所有边的方向要跟凸包边的方向一致。(呵呵,慢慢写吧,我是不会告诉你有数据有鬼畜点的,WA了自己拍吧)。然后还有一点,有些特判不能省,详情见我code的spj。

 #include<ctime>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
using namespace std; #define rhl 100
#define inf (1<<29)
#define esp (1e-10)
#define maxn 510
int ans = inf,m,n,tot,dis[maxn][maxn];
bool in[maxn]; inline double equal(double a,double b) { return fabs(a-b) < esp; } inline bool dd(double a,double b) { if (equal(a,b)) return true; return a >= b; }
inline bool dy(double a,double b) { if (equal(a,b)) return false; return a > b; } inline bool xd(double a,double b) { if (equal(a,b)) return true; return a <= b; } struct NODE
{
double x,y;
friend inline bool operator == (NODE a,NODE b) { return equal(a.x,b.x)&&equal(a.y,b.y); }
friend inline bool operator < (NODE a,NODE b) { if (a.x == b.x) return a.y < b.y; return a.x < b.x; }
friend inline NODE operator - (NODE a,NODE b) { return (NODE) {a.x - b.x,a.y - b.y}; }
friend inline double operator / (NODE a,NODE b) { return a.x*b.y-a.y*b.x; }
inline NODE ra()
{
int xx,yy;
do xx = rand()%rhl,yy = rand()%rhl;
while (equal(1.0*xx,x)||equal(1.0*yy,y));
return (NODE) {1.0*xx,1.0*yy};
}
inline void read() { scanf("%lf %lf",&x,&y); }
}pri[maxn],aim[maxn],ch[maxn];
struct LINE
{
double a,b,c;
inline bool on(NODE p) { return equal(,a*p.x+b*p.y+c); }
};
struct SEG
{
NODE a,b;
inline LINE extend() { return (LINE) {a.y-b.y,b.x-a.x,b.y*(a.x-b.x)-b.x*(a.y-b.y)}; }
inline bool on(NODE p)
{
if (p == a) return true;
if (p == b) return true;
return (dd(p.x,min(a.x,b.x))&xd(p.x,max(a.x,b.x)))&&(dd(p.y,min(a.y,b.y))&xd(p.y,max(a.y,b.y)));
}
}; inline bool para(LINE l1,LINE l2) { return equal(l1.a * l2.b,l1.b * l2.a); } inline NODE cp(LINE l1,LINE l2)
{
double a1 = l1.a,b1 = l1.b,c1 = l1.c;
double a2 = l2.a,b2 = l2.b,c2 = l2.c;
double ry = (c2*a1-c1*a2)/(b1*a2-b2*a1),rx = (c1*b2-c2*b1)/(b1*a2-b2*a1);
return (NODE) {rx,ry};
} inline void convex()
{
sort(aim+,aim+n+);
n = unique(aim+,aim+n+) - aim - ;
for (int i = ;i <= n;++i)
{
while (tot > &&(ch[tot] - ch[tot - ])/(aim[i] - ch[tot-]) <= ) --tot;
ch[++tot] = aim[i];
}
int k = tot;
for (int i = n-;i;--i)
{
while (tot > k &&(ch[tot] - ch[tot - ])/(aim[i] - ch[tot-]) <= ) --tot;
ch[++tot] = aim[i];
}
if (n > ) --tot;
ch[] = ch[tot];
} inline int find(NODE p)
{
NODE q = p.ra(); SEG s = (SEG) {p,q},t; LINE l = s.extend(),l1; int cnt;
cnt = ;
for (int i = ;i <= tot;++i)
{
t = (SEG) {ch[i],ch[i-]};
if ((t.extend()).on(p)&&t.on(p)) return false;
l1 = t.extend();
if (para(l,l1)) continue;
q = cp(l,l1);
if (dd(q.x,p.x)&&t.on(q)) ++cnt;
}
if (cnt & ) return true;
return false;
} inline bool cross(NODE p,NODE q)
{
for (int i = ;i <= tot;++i)
if (dy((q - p) / (ch[i] - p),)) return false;
return true;
} inline void ready()
{
sort(pri+,pri+m+);
m = unique(pri+,pri+m+) - pri - ;
for (int i = ;i <= m;++i) in[i] = find(pri[i]);
memset(dis,0x7,sizeof(dis));
for (int i = ;i <= m;++i) if (!in[i])
for (int j = ;j <= m;++j)
if (i != j && !in[j] &&dis[j][i] > maxn)
if (cross(pri[i],pri[j]))
dis[i][j] = ;
} inline void floyd()
{
for (int k = ;k <= m;++k)
for (int i = ;i <= m;++i)
if (dis[i][k] < maxn)
for (int j = ;j <= m;++j)
dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);
for (int i = ;i <= m;++i) ans = min(dis[i][i],ans);
if (ans > maxn) ans = -;
for (int i = ;i <= m;++i)
for (int j = i+;j <= m;++j)
{
SEG s = (SEG) {pri[i],pri[j]}; int k;
for (k = ;k <= n;++k)
if (!(equal((aim[k]-pri[i])/(aim[k]-pri[j]),)&&s.on(aim[k]))) break;
if (k == n + ) { ans = ; break; }
}
printf("%d",ans);
} inline void spj() { if (n == ) for (int i = ;i <= m;++i) if (pri[i] == aim[]) puts(""),exit(); } int main()
{
freopen("1027.in","r",stdin);
freopen("1027.out","w",stdout);
srand();
scanf("%d %d",&m,&n); double w;
for (int i = ;i <= m;++i)
pri[i].read(),scanf("%lf",&w);
for (int i = ;i <= n;++i)
aim[i].read(),scanf("%lf",&w);
convex();
spj();
ready();
floyd();
fclose(stdin); fclose(stdout);
return ;
}

BZOJ 1027 合金的更多相关文章

  1. [BZOJ]1027 合金(JSOI2007)

    不知道该如何评价吧,很神的一道题,就算是10年前的题目也不可小觑啊. Description 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁 ...

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

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1027 分析: 首先因为一个合金的和为1,所以考虑2个材料合金能否合成一个需求合金的时候 ...

  3. bzoj 1027 [JSOI2007]合金(计算几何+floyd最小环)

    1027: [JSOI2007]合金 Time Limit: 4 Sec  Memory Limit: 162 MBSubmit: 2970  Solved: 787[Submit][Status][ ...

  4. BZOJ 1027 [JSOI2007]合金

    1027: [JSOI2007]合金 Time Limit: 4 Sec  Memory Limit: 162 MBSubmit: 2605  Solved: 692[Submit][Status][ ...

  5. 【BZOJ 1027】[JSOI2007]合金

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1027 [题意] [题解] 因为和为1; 所以只要知道两个属性第三个属性就能用1减出来了 ...

  6. BZOJ 1027 JSOI2007 合金 计算几何+Floyd

    题目大意:给定一些合金,选择最少的合金,使这些合金能够按比例合成要求的合金 首先这题的想法特别奇异 看这题干怎么会想到计算几何 并且计算几何又怎么会跟Floyd挂边 好强大 首先因为a+b+c=1 所 ...

  7. BZOJ 1027 [JSOI2007]合金 ——计算几何

    我们可以把每一种金属拆成一个二维向量,显然第三维可以计算出来,是无关的. 我们只需要考虑前两维的情况,显然可以构成点集所形成的凸包内. 然后我们枚举两两的情况,然后可以发现如果所有的点都在一侧是可以选 ...

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

    参考:https://www.cnblogs.com/zhuohan123/p/3237246.html 因为一c可以由1-a-b得出,所以删掉c,把a,b抽象成二维平面上的点.首先考虑一个客户需求能 ...

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

    题解就看这位仁兄的吧-不过代码还是别看他的了- 同样的方法-我200ms,他2000ms. 常数的幽怨- CODE #include <bits/stdc++.h> using names ...

随机推荐

  1. IAP内购 返回的产品数量为0

    上个月搞IAP,提交到appstore审核被拒,根据附件截图 可以知道是请求产品信息的时候,产品数量返回0了. 返回产品数量为0 要么是Itunes Connect 里面的Contracts Tax ...

  2. android:ImageView 和ImageButton的区别

    1.继承不同: java.lang.Object ↳ android.view.View ↳android.widget.ImageView ↳ android.widget.ImageButton ...

  3. [TypeScript] Understanding Generics with RxJS

    Libraries such as RxJS use generics heavily in their definition files to describe how types flow thr ...

  4. Java语言基础(二)

    Java语言基础(二) 一.变量续 (1).变量有明确的类型 (2).变量必须有声明,初始化以后才能使用 (3).变量有作用域,离开作用域后自动回收 变量作用域在块内有效 (4).在同一定义域中变量不 ...

  5. 关于 Android 进程保活,你所需要知道的一切

    早前,我在知乎上回答了这样一个问题:怎么让 Android 程序一直后台运行,像 QQ 一样不被杀死?.关于 Android 平台的进程保活这一块,想必是所有 Android 开发者瞩目的内容之一.你 ...

  6. Java基础知识强化之集合框架笔记15:List集合的特点

    1. List集合的特点 List本身也是一个接口,如下: public interface List<E> extends Collection<E> (1)List是有序的 ...

  7. htmlentities() 函数

    Definition and Usage定义和用法 The htmlentities() function converts characters to HTML entities.htmlentit ...

  8. 第三篇:python高级之生成器&迭代器

    python高级之生成器&迭代器   python高级之生成器&迭代器 本机内容 概念梳理 容器 可迭代对象 迭代器 for循环内部实现 生成器 1.概念梳理 容器(container ...

  9. ToString格式.

    C 货币 2.5.ToString("C") ¥2.50 D 十进制数 25.ToString("D5") 00025 E 科学型 25000.ToString ...

  10. (转载)Javascript 进阶 作用域 作用域链

    载请标明出处:http://blog.csdn.net/lmj623565791/article/details/25076713 一直觉得Js很强大,由于长期不写js代码,最近刚好温故温故. 1.J ...