$bzoj1027-JSOI2007$ 合金 计算几何 最小环
- 题面描述
- 某公司加工一种由铁、铝、锡组成的合金。他们的工作很简单。首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同。然后,将每种原材料取出一定量,经过融解、混合,得到新的合金。新的合金的铁铝锡比重为用户所需要的比重。 现在,用户给出了\(n\)种他们需要的合金,以及每种合金中铁铝锡的比重。公司希望能够订购最少种类的原材料,并且使用这些原材料可以加工出用户需要的所有种类的合金。
- 输入格式
- 第一行两个整数\(m\)和\(n\) \((m, n \leq 500)\),分别表示原材料种数和用户需要的合金种数。第\(2\)到\(m + 1\)行,每行三个实数\(a, b, c\) \((a, b, c \geq 0 且 a + b + c = 1)\),分别表示铁铝锡在一种原材料中所占的比重。第\(m + 2\)到\(m +n + 1\)行,每行三个实数\(a, b, c\) \((a, b, c \geq 0 且 a + b + c = 1)\),分别表示铁铝锡在一种用户需要的合金中所占的比重。
- 输出格式
- 一个整数,表示最少需要的原材料种数。若无解,则输出\(–1\)。
- 题解
- 拿到题目,瞬间懵了,这是个啥?先考虑简化的问题,如果只有一维即\(\{a_i\}\),对于\(a_x,a_y\)\((a_x\leq a_y)\)能组成的数在\([a_x,a_y]\)中;再考虑二维,不难推广成\((x_1,y_1),(x_2,y_2)\)能组成的点为\((x_1,y_1)(x_2,y_2)\)线段上的点。
- 再看一眼题,我们能惊奇地发现题中表面上是三维的,但最后一维完全由前两维确定\(c=1-a-b\),也将是三维上的一个确定平面上的点,也就是说我们只需要考虑二维。
- 再回过头去看二维的情况,当\(3\)个点能够合成的合金是\(3\)个点围成的三角形内。
- 如何理解?对于\(3\)个点\(p_1,p_2,p_3\), \(p_1p_2,p_2p_3,p_1p_3\)为\(2\)个物品能合成的合金,再用这些合成的合金与其它融合为其连线段,故三角形由无数条连线段构成。
- 这个结论能够很容易地推广到\(n\)个点合成。
- 我们再将线段加上方向变成向量,当点在该向量顺时针\(180°\)内称为该向量右侧,当点在该向量逆时针\(180°\)内称为该向量右侧。
- 通过玩数据,我们不难发现最终能够合成所有目标合金为原合金组成的封闭图形,并能够围住所有目标合金。而进一步,当我们将该封闭图形按顺时针定方向后,所有目标合金均在这些向量右侧。
- 我们对每个向量\((x_1,y_1)(x_2,y_2)\)判断目标点是否均在一侧(左\(/\)右),在左侧\((x_1,y_1)\to (x_2,y_2)\),在右侧\((x_2,y_2)\to (x_1,y_1)\),即强制转化为向量右侧,那么如果一个点能通过一些向量回到自己,就一定形成包含所有目标点的封闭图形,那么我们用\(floyd\)找最小环即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN=505;
const double eps=1e-10;
int dis[MAXN][MAXN];
int n,m;
struct rec{
double x,y;
double operator * (const rec& b) const {
return x*b.y-y*b.x;
}
rec operator - (const rec& b) const {
return (rec){x-b.x,y-b.y};
}
} a[MAXN],b[MAXN];
bool inc(rec x,rec y){
if (x.x>y.x) swap(x,y);
for (int i=1;i<=m;i++){
if (b[i].x<x.x||b[i].x>y.x) return 0;
}
if (x.y>y.y) swap(x,y);
for (int i=1;i<=m;i++){
if (b[i].y<x.y||b[i].y>y.y) return 0;
}
return 1;
}
int jud(rec x,rec y){
int cnt1=0,cnt2=0;
for (int i=1;i<=m;i++){
double t=(x-y)*(b[i]-y);
if (t>eps) cnt1++;
if (t<-eps) cnt2++;
if (cnt1*cnt2>0) return 0;
}
if (cnt1==0&&cnt2==0&&inc(x,y)) return printf("2\n"),-1;
if (cnt1>0) return 1;
if (cnt2>0) return 2;
return 3;
}
bool spj(){
for (int i=1;i<=n;i++){
if (fabs(a[i].x-a[1].x)>eps||fabs(a[i].y-a[1].y)>eps) return 0;
}
for (int i=1;i<=m;i++){
if (fabs(b[i].x-a[1].x)>eps||fabs(b[i].y-a[1].y)>eps) return 0;
}
printf("1\n");
return 1;
}
int main(){
scanf("%d%d",&n,&m);
double tmp;
for (int i=1;i<=n;i++) scanf("%lf%lf%lf",&a[i].x,&a[i].y,&tmp);
for (int i=1;i<=m;i++) scanf("%lf%lf%lf",&b[i].x,&b[i].y,&tmp);
if (spj()) return 0;
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++) dis[i][j]=1e8;
}
for (int i=1;i<=n;i++){
for (int j=i+1;j<=n;j++){
int t=jud(a[i],a[j]);
if (t==-1) return 0;
if (t==1) dis[i][j]=1;
if (t==2) dis[j][i]=1;
if (t==3) dis[i][j]=dis[j][i]=1;
}
}
int ans=1e8;
for (int k=1;k<=n;k++){
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
// for (int i=1;i<=n;i++){
// for (int j=1;j<=n;j++) printf("%d ",dis[i][j]);
// printf("\n");
// }
for (int i=1;i<=n;i++) ans=min(ans,dis[i][i]);
if (ans==1e8||ans<=2) printf("-1\n");
else printf("%d\n",ans);
return 0;
}
随机推荐
- 如何注册facebook应用
最近项目中要做第三方登录,其中就有facebook的,下面讲解一下如何在facebook中创建应用 1.登录facebook的开发者平台(https://developers.facebook.com ...
- Jrebel 独立部署tomcat 远程同步项目
一直在用 jrebel 感觉热部署的 功能,修改xml配置文件等,省去了很多的重新启动的时间. 由于偶然间发现 jrebel 还有remote 路由功能.这样,在服务器端用jrebel部署的项目和本地 ...
- 通过cat方式生成yum源
cat >> /etc/yum.repos.d/centos7.repo << EOF[test-iso7]name=CentOS- - Mediabaseurl=http:/ ...
- Java虚拟机学习(1): 类加载机制
转自:微信公共号ImportNew 来源:java2000_wl 链接:blog.csdn.net/java2000_wl/article/details/8040633 JVM把class文件加载的 ...
- 编写高质量代码改善C#程序的157个建议——建议149:使用表驱动法避免过长的if和switch分支
建议149:使用表驱动法避免过长的if和switch分支 随着代码变得复杂,我们很容易被过长的if和switch分支困扰. 一个类枚举类型Week如下: enum Week { Monday, Tue ...
- 设计模式1---单例模式(Singleton pattern)
单例模式Singleton 面试的时候,问到许多年轻的Android开发他所会的设计模式是什么,基本上都会提到单例模式,但是对 单例模式也是一知半解,在Android开发中我们经常会运用单例模式,所以 ...
- 基于FPGA的XPT2046触摸控制器设计
基于FPGA的XPT2046触摸控制器设计 小梅哥编写,未经许可,文章内容和所涉及代码不得用于其他商业销售的板卡 本实例所涉及代码均可通过向 xiaomeige_fpga@foxmail.com 发 ...
- Elasticsearch 5.6.5 安装head插件
head安装包,下载地址:https://github.com/mobz/elasticsearch-head/archive/master.zip head 插件不能放在elasticsearch- ...
- 基于SSH的记账管理系统设计与实现-JavaWeb项目-有源码
开发工具:Myeclipse/Eclipse + MySQL + Tomcat 项目简介: Java记账管理系统主要用于财务人员可以从账务中判断公司的发展方向.对个人和家庭而言,通过记账可以制定日后的 ...
- Centos7 因内存 可用大小不足,被killed的解决办法
Linux的内存分配采取的是一种更加积极的分配策略,它假设应用申请了内存空间后并不会立即去使用它,所以允许一定量的超售,当应用真的需要使用它的时候,操作系统可能已经通过回收了其他应用的内存空间而变得有 ...