【BZOJ 1027】[JSOI2007]合金

【题目链接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1027

【题意】

【题解】

因为和为1;
所以只要知道两个属性第三个属性就能用1减出来了;
然后把每个合金材料化为平面坐标上的二维坐标;
两个合金能够合成的新合金的坐标就在这两个合金的连线上。
你可以假设两个合金的量分别为a,b;
对于某一种物质
新的合金该物质的含量为
(ap1+bp2)/(a+b)
=q*p1+w*p2;
这里(q+w)=1
然后代入两点式可证新的点必然在其上.
所以两个合金能够合成的新的合金必然在它们的连线上.
然后有多个合金。
要求你把这些合金合成客户所需要的合金。
可以想象成两个点集S1和S2
要在S1中选择最少的点集;
使得这些点集形成的闭包包围住了整个S2;
(可以证明只要闭包包住了S2,则S2里面的点集都能得到);
然后用计算几何搞出来S1中任意两个点(i,j)是否S2整个在其左侧.
如果是的话在(i,j)之间连一条边,边权为1;
然后求最小环就是答案了;
这里get到了求最小环的新姿势。
然后这个程序漏了两种情况;
就是ans=1和ans=2的情况。
对于这两种情况是要特判的;
因为这两种情况不是一个闭包了(对应了一个点和一条线)
没办法用闭包涉及到。
所以要加上一个点和两个点的特判;
(很懒并没有加上)
数据很弱啊,不想加了。知道就好。

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%lld",&x)
#define ref(x) scanf("%lf",&x)

typedef pair<int, int> pii;
typedef pair<LL, LL> pll;

const int dx[9] = { 0,1,-1,0,0,-1,-1,1,1 };
const int dy[9] = { 0,0,0,-1,1,-1,1,-1,1 };
const double pi = acos(-1.0);
const int N = 510;
const int INF = 0x3f3f3f3f;

struct point
{
    double x, y;
    point operator -(const point z)
    {
        point re;
        re.x = x - z.x;
        re.y = y - z.y;
        return re;
    }
    double operator * (const point z)
    {
        return x*z.y - y*z.x;
    }
    double operator ^ (const point z)
    {
        return x*z.x + y*z.y;
    }
} a[N], b[N];

int m, n;
int d[N][N], f[N][N];
int ans = INF;

void input_data()
{
    rei(m), rei(n);
    double t;
    rep1(i, 1, m)
    {
        ref(a[i].x), ref(a[i].y), ref(t);
    }
    rep1(i, 1, n)
    {
        ref(b[i].x), ref(b[i].y), ref(t);
    }
}

void ga()
{
    memset(d, 0x3f, sizeof d);
    rep1(i,1,m)
        rep1(j, 1, m) 
        {
            int k;
            for (k = 1; k <= n;k++)
            {
                double cross = (a[i] - b[k])*(a[j] - b[k]);
                if (cross > 1e-7)
                    break;
                if (fabs(cross) < 1e-7 && (a[i] - b[k] ^ a[j] - b[k]) > 1e-7)
                    break;
            }
            if (k == n + 1)
                d[i][j] = 1;
        }

}

void fl()
{
    memcpy(f, d, sizeof f);
    rep1(k,1,m)
        rep1(i,1,m)
            if (f[i][k]<INF)
                rep1(j, 1, m)
                {
                    f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
                }
    rep1(i, 1, m)
        ans = min(ans, f[i][i]);
}

void o()
{
    if (ans == INF)
    {
        puts("-1");
        return;
    }
    printf("%d\n", ans);
}

int main()
{
    //freopen("F:\\rush.txt", "r", stdin);
    input_data();
    ga();
    fl();
    o();
    //printf("\n%.2lf sec \n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}
posted @ 2017-10-04 18:45  AWCXV  阅读(145)  评论(0编辑  收藏  举报