# 【BZOJ】1027: [JSOI2007]合金（凸包+floyd）

http://www.lydsy.com/JudgeOnline/problem.php?id=1027

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define error(x) (!(x)?puts("error"):0)
#define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }

const double eps=1e-6;
int dcmp(double x) { return abs(x)<eps?0:(x<0?-1:1); }
struct ipt { double x, y; ipt(double _x=0, double _y=0) : x(_x), y(_y) {} };
bool operator== (ipt &a, ipt &b) { return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0; }
double icross(ipt &a, ipt &b, ipt &c) {
static double x1, x2, y1, y2;
x1=a.x-c.x; y1=a.y-c.y;
x2=b.x-c.x; y2=b.y-c.y;
return x1*y2-x2*y1;
}
double idot(ipt &a, ipt &b, ipt &c) {
static double x1, x2, y1, y2;
x1=a.x-c.x; y1=a.y-c.y;
x2=b.x-c.x; y2=b.y-c.y;
return x1*x2+y1*y2;
}
bool cmp(const ipt &a, const ipt &b) { return a.x==b.x?a.y<b.y:a.x<b.x; }
void tu(ipt *p, ipt *s, int n, int &top) {
sort(p, p+n, cmp);
top=-1;
rep(i, n) {
while(top>0 && dcmp(icross(p[i], s[top], s[top-1]))>=0) --top;
s[++top]=p[i];
}
static int k;
k=top;
for3(i, n-2, 0) {
while(top>k && dcmp(icross(p[i], s[top], s[top-1]))>=0) --top;
s[++top]=p[i];
}
if(n>1) --top;
++top;
}
bool PonS(ipt &a, ipt &p1, ipt &p2) { if(a==p1 || a==p2) return true; return dcmp(icross(a, p1, p2))==0 && dcmp(idot(p1, p2, a))<0; }

const int N=505, oo=~0u>>2;
int d[N][N], n, m, ans=oo;
ipt t[N], a[N], b[N];
bool checktu() {
rep(i, n) rep(j, m) if(dcmp(icross(b[j], a[i], a[i+1]))<0) return 0;
return 1;
}
bool check(ipt &x, ipt &y) {
rep(i, m) if(dcmp(icross(b[i], x, y))<0) return 0;
return 1;
}
bool spj() {
int flag;
rep(i, n) { flag=1; rep(j, m) if(!(a[i]==b[j])) { flag=0; break; } if(flag) { puts("1"); return 1; } }
rep(i, n) for1(j, i+1, n-1) {
flag=1;
rep(k, m) if(!PonS(b[k], a[i], a[j])) { flag=0; break; }
if(flag) { puts("2"); return 1; }
}
return 0;
}

int main() {
rep(i, n) scanf("%lf%lf%lf", &t[i].x, &t[i].y, &tt);
rep(i, m) scanf("%lf%lf%lf", &b[i].x, &b[i].y, &tt);
tu(t, a, n, n); a[n]=a[0];
if(!checktu()) { puts("-1"); return 0; }
if(spj()) return 0;
rep(i, n) rep(j, n) d[i][j]=oo;
rep(i, n) rep(j, n) if(i!=j) { if(check(a[i], a[j])) d[i][j]=1; else if(j>i) break; }
rep(k, n) rep(i, n) rep(j, n) d[i][j]=min(d[i][j], d[i][k]+d[k][j]);
rep(i, n) ans=min(ans, d[i][i]);
printf("%d\n", ans<=2?-1:ans);
return 0;
}

\begin{align} aX_A+(1-a)X_B & = X_C \\ aY_A+(1-a)Y_B & = Y_C \\ 0<=a<=1 \\ \end{align}

//upd:wiki了一下...这个就是凸包的线性意义...

//即

$$S=\{\sum_{x_i \in X} t_ix_i | t_i \in [0, 1] \}$$

posted @ 2015-01-02 21:51  iwtwiioi  阅读(489)  评论(1编辑  收藏  举报