• 【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
    ", ans);
    }
    
    int main()
    {
        //freopen("F:\rush.txt", "r", stdin);
        input_data();
        ga();
        fl();
        o();
        //printf("
    %.2lf sec 
    ", (double)clock() / CLOCKS_PER_SEC);
        return 0;
    }
    
  • 相关阅读:
    MySql.Data.dll的版本
    发现一个“佛系记账本”
    坚果云无法同步SVN文件夹
    Kali Linux打开多个终端窗口
    修改Kali Linux终端主题
    Kali Linux搜索软件包
    指定无线网卡监听信道
    解决Aireplay-ng信道问题
    查看干扰进程
    使用Kali官网提供的虚拟机系统
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626555.html
Copyright © 2020-2023  润新知