博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ1027 [JSOI2007]合金 【计算几何 + floyd】
阅读量:4697 次
发布时间:2019-06-09

本文共 2420 字,大约阅读时间需要 8 分钟。

题目

  某公司加工一种由铁、铝、锡组成的合金。他们的工作很简单。首先进口一些铁铝锡合金原材料,不同种类的

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

输入格式

  第一行两个整数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),分别表示铁铝锡在一种用户需要的合金中
所占的比重。

输出格式

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

输入样例

10 10

0.1 0.2 0.7

0.2 0.3 0.5

0.3 0.4 0.3

0.4 0.5 0.1

0.5 0.1 0.4

0.6 0.2 0.2

0.7 0.3 0

0.8 0.1 0.1

0.9 0.1 0

1 0 0

0.1 0.2 0.7

0.2 0.3 0.5

0.3 0.4 0.3

0.4 0.5 0.1

0.5 0.1 0.4

0.6 0.2 0.2

0.7 0.3 0

0.8 0.1 0.1

0.9 0.1 0

1 0 0

输出样例

5

题解

神题,蒟蒻跪了QAQ

首先第三个点是赘余的,只要两个点满足条件,第三个点一定满足条件,因为它们的和为都为同一个定值

这样我们就可以把材料和产品看做平面中的点,一个产品能被一些材料制作出来,当且仅当该产品在这些材料的凸包中。

问题就变成了使用A集合中的点形成的最小凸包围住B集合中的所有点

如果对A中的点i和j有所有B中的点都在其左侧,则连边i->j

求一个最小环即可。
此时B中的点一定在环上所有边左侧,即在该凸包内

#include
#include
#include
#include
#include
#define LL long long int#define REP(i,n) for (int i = 1; i <= (n); i++)#define Redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)#define eps 1e-9using namespace std;const int maxn = 505,maxm = 100005,INF = 1000000000;struct Point{
double x,y;}A[maxn],B[maxn];int N,M,G[maxn][maxn],ans = INF;double cross(const Point& a,const Point& b){
return a.x * b.y - a.y * b.x;}double dot(const Point& a,const Point& b){
return a.x * b.x + a.y * b.y;}Point line(const Point& a,const Point& b){
return (Point){b.x - a.x,b.y - a.y};}void floyd(){ REP(k,N) REP(i,N) REP(j,N) G[i][j] = min(G[i][j],G[i][k] + G[k][j]); REP(i,N) ans = min(ans,G[i][i]);}int main(){ fill(G[0],G[0] + maxn * maxn,INF); scanf("%d%d",&N,&M); double t,tt; REP(i,N) scanf("%lf%lf%lf",&A[i].x,&A[i].y,&t); REP(i,M) scanf("%lf%lf%lf",&B[i].x,&B[i].y,&t); for (int i = 1; i <= N; i++) for (int j = 1,k; j <= N; j++){ for (k = 1; k <= M; k++){ t = cross(line(A[i],B[k]),line(A[j],B[k])); tt = dot(line(A[i],B[k]),line(A[j],B[k])); if (t > eps) break; if (fabs(t) < eps && tt > eps) break; } if (k == M + 1) G[i][j] = 1; } floyd(); printf("%d\n",ans == INF ? -1 : ans); return 0;}

转载于:https://www.cnblogs.com/Mychael/p/8282715.html

你可能感兴趣的文章
SYS_CONTEXT 详细用法
查看>>
Pycharm配置autopep8让Python代码更符合pep8规范
查看>>
我的第一篇博客
查看>>
【C++算法与数据结构学习笔记------单链表实现多项式】
查看>>
C#垃圾回收机制
查看>>
31、任务三十一——表单联动
查看>>
python之hasattr、getattr和setattr函数
查看>>
maven使用阿里镜像配置文件
查看>>
Copy code from eclipse to word, save syntax.
查看>>
arguments.callee的作用及替换方案
查看>>
P2709 小B的询问
查看>>
PHP echo 和 print 语句
查看>>
第一讲 一个简单的Qt程序分析
查看>>
Centos 6.5下的OPENJDK卸载和SUN的JDK安装、环境变量配置
查看>>
poj 1979 Red and Black(dfs)
查看>>
【.Net基础03】HttpWebRequest模拟浏览器登陆
查看>>
zTree async 动态参数处理
查看>>
Oracle学习之常见错误整理
查看>>
数据库插入数据乱码问题
查看>>
altium annotate 选项设置 complete existing packages
查看>>