感觉网上很多题解写的似乎不清楚,这里说一下我的思路
显然对于每个用户的材料(设其比例为Ai,Bi,Ci),
我们要么最多用3种原料(设其比例为ai,bi,ci)混合成需要材料,要么一定混合不成,具体原因往下看
我们设这3种原料所取比例为x1,x2,x3,可得
x1*a1+x2*a2+x3*a3=Ai
x1*b1+x2*b2+x3*b3=Bi
x1*(1-a1-b1)+x2*(1-a2-b2)+x3*(1-a3-b3)=1-Ai-Bi
整理第三个式子可得x1+x2+x3=1 x3=1-x1-x2 (注意这里x1,x2,x3>=0)
带回到前两个式子可得
x1*a1+x2*a2+(1-x1-x2)*a3=Ai
x1*b1+x2*b2+(1-x1-x2)*b3=Bi
整理可得
x1*(a1-a3)+x2*(a2-a3)=Ai-a3
x1*(b1-b3)+x2*(b2-b3)=Bi-b3
看到这个式子大家仔细想就会发现,这其实就是:
向量(a1-a3,b1-b3)和(a2-a3,b2-b3)能否表示向量(Ai-a3,Bi-b3)
根据平面向量的理论我们知道上面的结论是正确的
学过向量的同学可能还会听过这样一个结论(很好证)
设OABC四点,B在线段AC上,O不与ABC共线
则向量OB=a向量OA+b向量OC 一定满足a+b=1 而这里我们的要求也是x1+x2<=1
也就是如果把ai,bi和A,B看做材料点(ai,bi)和原料点(Ai,Bi)
如果用户所需材料i能被原料融合,当且仅当存在三个原料点构成的三角形能把材料点围起来
于是下面的思路就很明显了,我们先求出原料点所组成的凸包,如果所有用户都在凸包内则有解否则无解
接下来我们要找的是最少凸包上的点组成的多边形就能把所有原料点包含了
首先我们要理解什么是包含,我们从凸包一点出发,沿着下凸线到上凸线的顺序走回起点
这样凸包上的每条边就是一个向量,包含的意思就是:每个原料点都必须在每个向量的左边(叉积判断)
于是这就好办了,于是我们穷举向量的起点i终点j,如果所有原料点都在这个向量的左边那么d[i,j]=1 否则d[i,j]=inf
下面我们只要求出一个最小环即可,这可以用floyd搞定
注意这里凸包上是不能存在三点共线的
比较恶心的是这道题要注意精度问题

 const eps=1e-10;
type point=record
x,y:double;
end; var a,b:array[..] of point;
w:array[..] of longint;
f:array[..,..] of longint;
ans,i,j,k,p,n,m:longint;
ch:boolean; function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end; procedure swap(var a,b:point);
var c:point;
begin
c:=a;
a:=b;
b:=c;
end; procedure sort(l,r:longint);
var i,j:longint;
p:point;
begin
i:=l;
j:=r;
p:=a[(l+r) shr ];
repeat
while (a[i].x<p.x) or (a[i].x=p.x) and (a[i].y<p.y) do inc(i);
while (p.x<a[j].x) or (a[j].x=p.x) and (p.y<a[j].y) do dec(j);
if not(i>j) then
begin
swap(a[i],a[j]);
inc(i);
dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; function cross(a,b,c:point):double;
begin
exit((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
end; function check:boolean;
var i,j:longint;
begin
dec(k);
for i:= to k do
for j:= to n do
if cross(a[w[i]],a[w[i+]],b[j])<-eps then exit(false);
exit(true);
end; begin
readln(m,n);
for i:= to m do
readln(a[i].x,a[i].x,a[i].y);
for i:= to n do
readln(b[i].x,b[i].x,b[i].y);
if n= then
begin
writeln();
halt;
end;
for i:= to m do
begin
ch:=true;
for j:= to n do
if (a[i].x<>b[j].x) or (a[i].y<>b[j].y) then
begin
ch:=false;
break;
end;
if ch then //这里特判一下
begin
writeln();
halt;
end;
end;
sort(,m);
k:=;
w[]:=;
for i:= to m do
begin
while (k>) and (cross(a[w[k-]],a[w[k]],a[i])<eps) do dec(k);
inc(k); w[k]:=i;
end;
j:=k;
for i:=m- downto do
begin
while (k>j) and (cross(a[w[k-]],a[w[k]],a[i])<eps) do dec(k);
inc(k); w[k]:=i;
end;
if check then
begin
for i:= to k do
for j:= to k do
begin
f[i,j]:=m;
if i<>j then
begin
ch:=true;
for p:= to n do
if cross(a[w[i]],a[w[j]],b[p])<-eps then
begin
ch:=false;
break;
end;
if ch then f[i,j]:=;
end;
end; for p:= to k do
for i:= to k do
for j:= to k do
f[i,j]:=min(f[i,j],f[i,p]+f[p,j]);
ans:=m;
for i:= to k do
ans:=min(ans,f[i,i]);
writeln(ans);
end
else writeln(-);
end.

bzoj1027的更多相关文章

  1. 【bzoj1027】合金

    [bzoj1027]合金 分析 数形结合+计算几何+Floyd最小环. http://blog.csdn.net/popoqqq/article/details/40539273 虽然这样占大家的很不 ...

  2. bzoj1027【JSOI2007】合金

    题目描述 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的合金.新的合金 ...

  3. bzoj1027 [JSOI2007]合金

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

  4. bzoj1027 [HNOI2004]打鼹鼠

    [HNOI2004]打鼹鼠 2014年5月2日2,8605 Description 鼹鼠是一种很喜欢挖洞的动物,但每过一定的时间,它还是喜欢把头探出到地面上来透透气的.根据这个特点阿Q编写了一个打鼹鼠 ...

  5. bzoj1027 状压dp

    https://www.lydsy.com/JudgeOnline/problem.php?id=1072 题意 给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除 试了一下发现暴力可过 ...

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

    http://www.lydsy.com/JudgeOnline/problem.php?id=1027 因为x+y+z=1,所以z=1-x-y 第三维可以忽略 将x,y 看做 平面上的点 简化问题: ...

  7. BZOJ1027 [HNOI2004]打鼹鼠 【dp】

    1207: [HNOI2004]打鼹鼠 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3647  Solved: 1746 [Submit][Sta ...

  8. BZOJ1027 [JSOI2007]合金 【计算几何 + floyd】

    题目 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的 原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的合金.新的合金的 ...

  9. bzoj题解汇总(1021~1031)

    bzoj1021:普通dp bzoj1022:裸的Anti-Nim 必胜:①sg=0且所有不超过1 ②sg>1且存在至少一个超过1 bzoj1023:http://www.cnblogs.com ...

随机推荐

  1. (转)boost::bind介绍

    转自:http://www.cnblogs.com/sld666666/archive/2010/12/14/1905980.html 这篇文章介绍boost::bind()的用法, 文章的主要内容是 ...

  2. 关于js与php互相传值的介绍【转载+自身总结】

    JS是前台的语言,PHP是后台的语言,初学时会经常出现前后台分不清的情况(我当初就是这样的,现在有时也在犯),我当初的想法是就把前后台当成两个岛,他们是无法跨越的,HTML就像一座桥,当你想要把一座岛 ...

  3. Python3 IO

    在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中 ...

  4. thinkphp验证码的实现

    两种验证码验证实现,一种直接在form表单提交按钮实现验证,一种使用ajax传递参数实现验证: 1.直接在form表单提交按钮实现验证,在控制器VerifyController.class.php中写 ...

  5. 捕获ClientDataSet.ApplyUpdates和SocketConnection异常

    核心提示:如何捕获ClientDataSet.ApplyUpdates的错误,不用ReconcileError... var cdsEmp:TClientDataSet; //保存 procedure ...

  6. hdu 4358 Boring counting 离散化+dfs序+莫队算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4358 题意:以1为根节点含有N(N <= 1e5)个结点的树,每个节点有一个权值(weight ...

  7. WebService 学习过程

    //------------------------------------------------------------------------------------------ //windo ...

  8. 【hibernate】spring+ jpa + hibername 配置过程遇到的问题

    org.springframework.data.jpa.domain.support.AuditingEntityListener Auditing: 审计:查账Hades:Hades是一个开源库, ...

  9. XSS传染基础——JavaScript中的opener、iframe

    最近研究XSS,根据etherDream大神的博客 延长XSS生命周期 写了一个子页面父页面相互修改的demo. 一. 子页面.父页面相互修改——window.opener.window.open 在 ...

  10. SQL中Case的使用方法(下篇)(转)

    接上篇 四,根据条件有选择的UPDATE. 例,有如下更新条件 工资5000以上的职员,工资减少10% 工资在2000到4600之间的职员,工资增加15% 很容易考虑的是选择执行两次UPDATE语句, ...