bzoj1027 [JSOI2007]合金
1027: [JSOI2007]合金
Time Limit: 4 Sec Memory Limit: 162 MB
Submit: 2671 Solved: 703
[Submit][Status][Discuss]
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
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
HINT
Source
题意:见分析
分析:我把n和m的意义相调转
即n代表原材料种数,m代表所需产品数
显然,第三维不需要,因为a+b+c==1,前两维确定即确定第三维
当n==2时,若一个产品可以通过这两种原材料组合而成那么一定有
materia1.a*k+materia2.a*(1-k) == product.a
materia1.b*k+materia2.b*(1-k) == product.b
等等,这个形式。。。如果把它们的a,b表示成二元组(a, b),那么。。。。
不就是说明如果把a当成横坐标,b当成纵坐标,
那么这两种原材料所能组成的产品一定在两端点为(materia1.a, materia1.b)(materia2.a, materia2.b)的线段上吗?
那么如果n == 3时,显然根据向量的加减,所能组成的产品一定在这三点围成的三角形里
当n==k时,同理,所能组成的产品一定在这几个点所围成的图形里(即这几个原材料的点所形成的凸包里)
但显然,构成凸包的最少点未必就是包住产品点的最少点数
那么我们探究一下,
我们逆时针看那个围住产品点的图形
并称一个由原材料点构成的 能围住产品点的 图形为合法图形
探究合法图形的边有什么性质
显然,如果一条边可能属于一个合法图形,那么所有的产品点都在它的一侧,我们假定都在这条边的逆时针方向
(因为我们使用叉积判断,所以要这样,注意,我们是逆时针看那个合法图形的)
所以首先我们要枚举任意两个原材料点,判断它们所连的边是否合法。。。
然后我们根据所有的合法边,尝试围成一个点数最少的合法图形
等等。。。。。如果我们把每条边的长度设为1,那么点数的多少不就是那个图形(环)的长度吗!?
不就是最小环吗?
对于最小环,我推荐一篇文章
http://www.cnblogs.com/Yz81128/archive/2012/08/15/2640940.html
我个人的理解:
一下见解不局限于本题,普适于所有有向图的最小环
每次在进行floyd的更新前(保证当前所有的最短路不包含k),算出环上的点最大为k(一定要有k)的最小的环
这样更新ans = min(ans, dis[i][j]+map[j][k]+map[k][i])
因为当前没有更新dis[i][j]所代表的最短路不包含k,如此便枚举出所有的 环上的点最大为k的环
然后再进行更新
当然由于本题的特殊性,并不需要完整的最小环算法
只需要求一遍点 i->点 i(就是回到自己)的最短路即可(同原来的floyd)
提供代码
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <ctime>
using namespace std;
typedef long long LL;
typedef double DB;
#define For(i, s, t) for(int i = (s); i <= (t); i++)
#define Ford(i, s, t) for(int i = (s); i >= (t); i--)
#define Rep(i, t) for(int i = (0); i < (t); i++)
#define Repn(i, t) for(int i = ((t)-1); i >= (0); i--)
#define rep(i, x, t) for(int i = (x); i < (t); i++)
#define MIT (2147483647)
#define INF (1000000001)
#define MLL (1000000000000000001LL)
#define sz(x) ((int) (x).size())
#define clr(x, y) memset(x, y, sizeof(x))
#define puf push_front
#define pub push_back
#define pof pop_front
#define pob pop_back
#define ft first
#define sd second
#define mk make_pair
inline void SetIO(string Name) {
string Input = Name+".in",
Output = Name+".out";
freopen(Input.c_str(), "r", stdin),
freopen(Output.c_str(), "w", stdout);
} const int N = ;
const DB Eps = 1e-;
inline int Cmp(DB a, DB b) ;
struct Point {
DB x, y; inline bool operator ==(const Point &A) const {
if(!Cmp(x, A.x) && !Cmp(y, A.y)) return ;
return ;
}
} A[N], B[N];
int n, m;
int Dp[N][N], Map[N][N]; inline void Input() {
scanf("%d%d", &n, &m);
DB c;
For(i, , n) scanf("%lf%lf%lf", &A[i].x, &A[i].y, &c);
For(i, , m) scanf("%lf%lf%lf", &B[i].x, &B[i].y, &c);
} inline int Cmp(DB a, DB b) {
if(a < b-Eps) return -;
if(a > b+Eps) return ;
return ;
} inline bool Cover(Point x) {
For(i, , m)
if(!(x == B[i])) return ;
return ;
} inline void Exit(string Ans) {
cout<<Ans<<"\n";
exit();
} inline DB Multi(Point O, Point A, Point B) {
return (A.x-O.x)*(B.y-O.y)-(A.y-O.y)*(B.x-O.x);
} inline bool Couple(Point O, Point A) {
For(i, , m) {
if(Cmp(Multi(O, A, B[i]), 0.0)) return ;
DB Left = O.x, Right = A.x, Up = O.y, Down = A.y;
if(Left > Right) swap(Left, Right);
if(Down > Up) swap(Up, Down);
if(Cmp(B[i].x, Left) < || Cmp(B[i].x, Right) > ||
Cmp(B[i].y, Down) < || Cmp(B[i].y, Up) > ) return ;
}
return ;
} inline bool Judge(Point O, Point A) {
For(i, , m)
if(Cmp(Multi(O, A, B[i]), 0.0) < ) return ;
return ;
} inline void Solve() {
if(!m) Exit("");
For(i, , n)
if(Cover(A[i])) Exit("");
For(i, , n)
For(j, i+, n)
if(Couple(A[i], A[j])) Exit(""); For(i, , n)
For(j, , n) Dp[i][j] = Map[i][j] = ;
For(i, , n)
For(j, , n) {
if(i == j) continue;
if(Judge(A[i], A[j])) Dp[i][j] = Map[i][j] = ;
} int Ans = ;
For(k, , n) {
For(i, , k-)
For(j, , k-)
Ans = min(Ans, Dp[i][j]+Map[j][k]+Map[k][i]); For(i, , n)
For(j, , n)
Dp[i][j] = min(Dp[i][j], Dp[i][k]+Dp[k][j]);
} if(Ans > n) Ans = -;
printf("%d\n", Ans);
} int main() {
#ifndef ONLINE_JUDGE
SetIO("");
#endif
Input();
Solve();
return ;
}
表示这题我原来想挫了,本来想先把原材料点搞个凸包,产品点搞个凸包,然后再用dp求原材料凸包上最少用多少
bzoj1027 [JSOI2007]合金的更多相关文章
- bzoj千题计划123:bzoj1027: [JSOI2007]合金
http://www.lydsy.com/JudgeOnline/problem.php?id=1027 因为x+y+z=1,所以z=1-x-y 第三维可以忽略 将x,y 看做 平面上的点 简化问题: ...
- BZOJ1027 [JSOI2007]合金 【计算几何 + floyd】
题目 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的 原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的合金.新的合金的 ...
- 【bzoj1027】合金
[bzoj1027]合金 分析 数形结合+计算几何+Floyd最小环. http://blog.csdn.net/popoqqq/article/details/40539273 虽然这样占大家的很不 ...
- bzoj 1027 [JSOI2007]合金(计算几何+floyd最小环)
1027: [JSOI2007]合金 Time Limit: 4 Sec Memory Limit: 162 MBSubmit: 2970 Solved: 787[Submit][Status][ ...
- BZOJ 1027 [JSOI2007]合金
1027: [JSOI2007]合金 Time Limit: 4 Sec Memory Limit: 162 MBSubmit: 2605 Solved: 692[Submit][Status][ ...
- [bzoj 1027][JSOI2007]合金(解析几何+最小环)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1027 分析: 首先因为一个合金的和为1,所以考虑2个材料合金能否合成一个需求合金的时候 ...
- 1027: [JSOI2007]合金 - BZOJ
Description 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的 ...
- [JSOI2007]合金
Description 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的 原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新 ...
- P4049 [JSOI2007]合金
传送门 我数学可能白学了-- 因为三个数加起来等于\(1\),那么只要用前两个数就能表示,那么就能把每一种金属看成一个二维向量.考虑只有两个向量的时候,设这两个向量为\(a,b\),那么一个向量\(c ...
随机推荐
- [Effective JavaScript 笔记] 第14条:当心命名函数表达式笨拙的作用域
js函数会根据上下文改变其含义. function double(x){return x*2;} 这是一个函数声明,也可以是一个命名函数表达式(named function expression),取 ...
- CreateRemoteThread远程线程注入Dll与Hook
CreateRemoteThread虽然很容易被检测到,但是在有些场合还是挺有用的.每次想用的时候总想着去找以前的代码,现在在这里记录一下. CreateRemoteThread远程注入 DWORD ...
- Coursera台大机器学习课程笔记13 -- Regularization
这一节讲的是正则化,在优化中一直会用到正则化项,上课的时候老师一句话代过,没有作过多的解释.听完这节课后, 才明白好大学和野鸡大学的区别有多大.总之,这是很有收获的一节课. 首先介绍了为什么要正则化, ...
- uc_client是如何与UCenter进行通信的
以用户登录为例介绍,其它注销,改密码,消息,头像,好友均类同. 从用户xxx在某一应用程序的login.php,输入用户名,密码讲起.先用uc_user_login函数到uc_server验证此用户和 ...
- PHP 遍历数组的方法汇总
1. foreach() foreach()是一个用来遍历数组中数据的最简单有效的方法. #example1: <?php $colors= array('red','blue','green' ...
- Apple Swift中英文开发资源集锦[apple swift resources]
找到的一些Apple Swift中英文资源原文链接,希望对大家有所帮助.欢迎大家补充,原始资源链接最好! The Swift Programming Language https://develope ...
- 解决ecshop登陆自动退出的莫名现象
最近在做ecshop的二次开发,程序发布后测试出现一个莫名的问题.点击几次页面后出现session丢失,需要重复登陆:本地怎么测试也都无法重现问题.一开始以为是修改程序的问题,可是怎么找都找不着问题所 ...
- codeforces A. Vasya and Digital Root 解题报告
题目链接:http://codeforces.com/problemset/problem/355/A 题目意思:找出某个经过最多四次dr(n)操作等于d的k位数. 千万不要想得太复杂,想得越简单 ...
- Android实现监测网络状态
本文主要用到了安卓监测网络状态变化功能,实现了WIFI,3G,无网络状态切换时发出通知的功能. 主要知识点 service broadcast 接口回调实现 service的基本知识 service可 ...
- grep -n 显示行号
[root@86 ~]# grep -n "StartDiscoverers" /usr/local/zabbix/etc/zabbix_server.conf 176:### O ...