zoukankan      html  css  js  c++  java
  • bzoj1027

    感觉网上很多题解写的似乎不清楚,这里说一下我的思路
    显然对于每个用户的材料(设其比例为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搞定
    注意这里凸包上是不能存在三点共线的
    比较恶心的是这道题要注意精度问题

      1 const eps=1e-10;
      2 type point=record
      3        x,y:double;
      4      end;
      5 
      6 var a,b:array[0..510] of point;
      7     w:array[0..510] of longint;
      8     f:array[0..510,0..510] of longint;
      9     ans,i,j,k,p,n,m:longint;
     10     ch:boolean;
     11 
     12 function min(a,b:longint):longint;
     13   begin
     14     if a>b then exit(b) else exit(a);
     15   end;
     16 
     17 procedure swap(var a,b:point);
     18   var c:point;
     19   begin
     20     c:=a;
     21     a:=b;
     22     b:=c;
     23   end;
     24 
     25 
     26 procedure sort(l,r:longint);
     27   var i,j:longint;
     28       p:point;
     29   begin
     30     i:=l;
     31     j:=r;
     32     p:=a[(l+r) shr 1];
     33     repeat
     34       while (a[i].x<p.x) or (a[i].x=p.x) and (a[i].y<p.y) do inc(i);
     35       while (p.x<a[j].x) or (a[j].x=p.x) and (p.y<a[j].y) do dec(j);
     36       if not(i>j) then
     37       begin
     38         swap(a[i],a[j]);
     39         inc(i);
     40         dec(j);
     41       end;
     42     until i>j;
     43     if l<j then sort(l,j);
     44     if i<r then sort(i,r);
     45   end;
     46 
     47 function cross(a,b,c:point):double;
     48   begin
     49     exit((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
     50   end;
     51 
     52 function check:boolean;
     53   var i,j:longint;
     54   begin
     55     dec(k);
     56     for i:=1 to k do
     57       for j:=1 to n do
     58         if cross(a[w[i]],a[w[i+1]],b[j])<-eps then exit(false);
     59     exit(true);
     60   end;
     61 
     62 begin
     63   readln(m,n);
     64   for i:=1 to m do
     65     readln(a[i].x,a[i].x,a[i].y);
     66   for i:=1 to n do
     67     readln(b[i].x,b[i].x,b[i].y);
     68   if n=0 then
     69   begin
     70     writeln(0);
     71     halt;
     72   end;
     73   for i:=1 to m do
     74   begin
     75     ch:=true;
     76     for j:=1 to n do
     77       if (a[i].x<>b[j].x) or (a[i].y<>b[j].y) then
     78       begin
     79         ch:=false;
     80         break;
     81       end;
     82     if ch then //这里特判一下
     83     begin
     84       writeln(1);
     85       halt;
     86     end;
     87   end;
     88   sort(1,m);
     89   k:=1;
     90   w[1]:=1;
     91   for i:=2 to m do
     92   begin
     93     while (k>1) and (cross(a[w[k-1]],a[w[k]],a[i])<eps) do dec(k);
     94     inc(k); w[k]:=i;
     95   end;
     96   j:=k;
     97   for i:=m-1 downto 1 do
     98   begin
     99     while (k>j) and (cross(a[w[k-1]],a[w[k]],a[i])<eps) do dec(k);
    100     inc(k); w[k]:=i;
    101   end;
    102   if check then
    103   begin
    104     for i:=1 to k do
    105       for j:=1 to k do
    106       begin
    107         f[i,j]:=m;
    108         if i<>j then
    109         begin
    110           ch:=true;
    111           for p:=1 to n do
    112             if cross(a[w[i]],a[w[j]],b[p])<-eps then
    113             begin
    114               ch:=false;
    115               break;
    116             end;
    117           if ch then f[i,j]:=1;
    118         end;
    119       end;
    120 
    121     for p:=1 to k do
    122       for i:=1 to k do
    123         for j:=1 to k do
    124           f[i,j]:=min(f[i,j],f[i,p]+f[p,j]);
    125     ans:=m;
    126     for i:=1 to k do
    127       ans:=min(ans,f[i,i]);
    128     writeln(ans);
    129   end
    130   else writeln(-1);
    131 end.
    View Code
  • 相关阅读:
    django-02框架-配置、静态文件和路由
    django-01框架-工程搭建
    python虚拟环境安装
    linux推送文件到另一台主机
    python2问题收集
    python diff json方法
    Linux expect详解
    python scp到远端机器
    shell远程执行命令(命令行与脚本)
    git操作
  • 原文地址:https://www.cnblogs.com/phile/p/4472974.html
Copyright © 2011-2022 走看看