BZOJ 1027 合金
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
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
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 合金的更多相关文章
- [BZOJ]1027 合金(JSOI2007)
不知道该如何评价吧,很神的一道题,就算是10年前的题目也不可小觑啊. Description 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁 ...
- [bzoj 1027][JSOI2007]合金(解析几何+最小环)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1027 分析: 首先因为一个合金的和为1,所以考虑2个材料合金能否合成一个需求合金的时候 ...
- bzoj 1027 [JSOI2007]合金(计算几何+floyd最小环)
1027: [JSOI2007]合金 Time Limit: 4 Sec Memory Limit: 162 MBSubmit: 2970 Solved: 787[Submit][Status][ ...
- BZOJ 1027 [JSOI2007]合金
1027: [JSOI2007]合金 Time Limit: 4 Sec Memory Limit: 162 MBSubmit: 2605 Solved: 692[Submit][Status][ ...
- 【BZOJ 1027】[JSOI2007]合金
[题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1027 [题意] [题解] 因为和为1; 所以只要知道两个属性第三个属性就能用1减出来了 ...
- BZOJ 1027 JSOI2007 合金 计算几何+Floyd
题目大意:给定一些合金,选择最少的合金,使这些合金能够按比例合成要求的合金 首先这题的想法特别奇异 看这题干怎么会想到计算几何 并且计算几何又怎么会跟Floyd挂边 好强大 首先因为a+b+c=1 所 ...
- BZOJ 1027 [JSOI2007]合金 ——计算几何
我们可以把每一种金属拆成一个二维向量,显然第三维可以计算出来,是无关的. 我们只需要考虑前两维的情况,显然可以构成点集所形成的凸包内. 然后我们枚举两两的情况,然后可以发现如果所有的点都在一侧是可以选 ...
- bzoj 1027: [JSOI2007]合金【凸包+Floyd】
参考:https://www.cnblogs.com/zhuohan123/p/3237246.html 因为一c可以由1-a-b得出,所以删掉c,把a,b抽象成二维平面上的点.首先考虑一个客户需求能 ...
- BZOJ 1027: [JSOI2007]合金 (计算几何+Floyd求最小环)
题解就看这位仁兄的吧-不过代码还是别看他的了- 同样的方法-我200ms,他2000ms. 常数的幽怨- CODE #include <bits/stdc++.h> using names ...
随机推荐
- 单元测试时候使用[ClassInitialize]会该方法必须是静态的公共方法,不返回值并且应采用一个TestContext类型的参数报错的解决办法
using Microsoft.VisualStudio.TestTools.UnitTesting; 如果该DLL应用的是 C:\Program Files\Microsoft Visual Stu ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(20)-权限管理系统-根据权限获取菜单
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(20)-权限管理系统-根据权限获取菜单 不知不觉到20讲,真是漫长的日子,可惜最近工作挺忙,要不可以有更多 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(19)-权限管理系统-用户登录
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(19)-权限管理系统-用户登录 我们之前做了验证码,登录界面,却没有登录实际的代码,我们这次先把用户登录先 ...
- C#和java和android中的NetWorkAdapter,httpRequest,WebView,json,xml
原文地址:http://blog.csdn.net/intbird C#NetWorkAdapter 20121011.======================================== ...
- C程序中唯一序列号的生成
在实际的软件开发项目中.常常会涉及唯一序列号的生成.本文以一个实际的程序为例,介绍了唯一序列号的生成过程. 本文生成的序列号的样式为:MMDDHHMINSS_XXXXXX. 程序例如以下: /**** ...
- SQL Server 2008 安装指南
一.安装需求: 1.硬件需求条件 硬件 需求 处理器 最低:1.4 GHz(x64处理器)注意:Windows Server 2008 for Itanium-Based Systems 版本需要In ...
- laydate时间组件在火狐浏览器下有多时间输入框时只能给第一个输入框赋值的问题
遇到的问题: laydate时间组件在火狐浏览器下有多时间输入框时只能给第一个输入框赋值的问题(safari下也有同样问题); 解决办法: 给laydate绑定id; 解决前代码: <input ...
- 一次项目中用到的php函数总结
最近做的一个项目,我把做的过程中用到的php函数总结一下.以后遇到类似的不用百度,直接看自己总结的就好了.都是一些简单基础的函数,随手记下.方便以后学习. 1.array_sum() 返回数组中的所有 ...
- 内联式css样式,直接写在现有的HTML标签中
CSS样式可以写在哪些地方呢?从CSS 样式代码插入的形式来看基本可以分为以下3种:内联式.嵌入式和外部式三种.这一小节先来讲解内联式. 内联式css样式表就是把css代码直接写在现有的HTML标签中 ...
- Sqoop import加载HBase案例详解
简单写一下如何将订单表sqoop到hbase表中的步骤. 下表: 1.通过hbase shell 打开hbase. 2.创建一个hbase表 create 'so','o' 3.将so表的数据导入到h ...