分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 前端开发

[JSOI2007]合金

发布时间:2023-09-06 01:43责任编辑:郭大石关键词:暂无标签

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

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

Sample Output

5
第三维可以由前两维确定,所以可以忽略
这样一个材料只有两个属性,把它变成一个坐标
对于两个材料,他们能合成的合金就是以两个点为端点的线段上的点
如果n个材料点构成的凸包囊括了所有合金点,就必然可行,因为一个合金点可以看作是某两个在凸包边上的点构成的线段上的点
如果有合金点在a[i]->a[j]左边,没有合金点在右边
那么建一条(i,j)权为1的边
如果没有在左边的点,就建一条(j,i)边
如果全在直线上,则不建边,特判
于是转化为了floyd求最小环
要特判所有点重点(可能输出1),和所有点在线段上(即输出2)
 ?1 #include<iostream> ?2 #include<cstdio> ?3 #include<cstring> ?4 #include<algorithm> ?5 #include<cmath> ?6 using namespace std; ?7 struct Node ?8 { ?9 ??double x,y; 10 }a[501],b[501]; 11 double eps=1e-8; 12 int dis[501][501],n,m,inf,ans; 13 Node operator -(Node u,Node v) 14 { 15 ??return (Node){u.x-v.x,u.y-v.y}; 16 } 17 double operator *(Node u,Node v) 18 { 19 ??return u.x*v.y-v.x*u.y; 20 } 21 bool spj() 22 {int i,j; 23 ??for (i=1;i<=n;i++) 24 ????if (fabs(a[i].x-a[1].x)>eps||fabs(a[i].y-a[1].y)>eps) return 0; 25 ??for (i=1;i<=m;i++) 26 ????if (fabs(b[i].x-a[1].x)>eps||fabs(b[i].y-a[1].y)>eps) return 0; 27 ??cout<<1<<endl; 28 ??return 1; 29 } 30 bool pd(Node x,Node y) 31 {int i,j; 32 ??if (x.x>y.x) swap(x,y); 33 ??for (i=1;i<=m;i++) 34 ????{ 35 ??????if (b[i].x<x.x||b[i].x>y.x) return 0; 36 ????} 37 ??if (x.y>y.y) swap(x,y); 38 ??for (i=1;i<=m;i++) 39 ????{ 40 ??????if (b[i].y<x.y||b[i].y>y.y) return 0; 41 ????} 42 ??return 1; 43 } 44 int judge(Node x,Node y) 45 {int i; 46 ??int c1=0,c2=0; 47 ??for (i=1;i<=m;i++) 48 ????{ 49 ??????double t=(y-x)*(b[i]-x); 50 ??????if (t>eps) c1++; 51 ??????if (t<-eps) c2++; 52 ??????if (c1*c2) return 0; 53 ????} 54 ??if (!c1&&!c2&&pd(x,y)) return -1; 55 ??if (c1) return 1; 56 ??if (c2) return 2; 57 ??return 3; 58 } 59 int main() 60 {int i,j,k; 61 ??double d; 62 ??cin>>n>>m; 63 ??for (i=1;i<=n;i++) 64 ????{ 65 ??????scanf("%lf%lf%lf",&a[i].x,&a[i].y,&d); 66 ????} 67 ??for (i=1;i<=m;i++) 68 ????{ 69 ??????scanf("%lf%lf%lf",&b[i].x,&b[i].y,&d); 70 ????} 71 ??if (spj()) return 0; 72 ??memset(dis,127/3,sizeof(dis)); 73 ??inf=dis[0][0]; 74 ??for (i=1;i<=n;i++) 75 ????{ 76 ??????for (j=i+1;j<=n;j++) 77 ????{ 78 ??????int p=judge(a[i],a[j]); 79 ??????if (p==-1) 80 ????????{ 81 ??????????cout<<2<<endl; 82 ??????????return 0; 83 ????????} 84 ??????if (p==1) dis[i][j]=1; 85 ??????else if (p==2) dis[j][i]=1; 86 ????} 87 ????} 88 ??for (k=1;k<=n;k++) 89 ????{ 90 ??????for (i=1;i<=n;i++) 91 ????if (dis[i][k]!=inf) 92 ????{ 93 ??????for (j=1;j<=n;j++) 94 ????????if (dis[i][k]+dis[k][j]<dis[i][j]) 95 ????????dis[i][j]=dis[i][k]+dis[k][j]; 96 ????} 97 ????} 98 ??ans=inf; 99 ??for (i=1;i<=n;i++)100 ????ans=min(ans,dis[i][i]);101 ??if (ans==inf) cout<<"-1";102 ??else printf("%d\n",ans);103 }

[JSOI2007]合金

原文地址:https://www.cnblogs.com/Y-E-T-I/p/8469721.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved