zoukankan      html  css  js  c++  java
  • 导弹拦截(升级版)JZOJ5354(提高)

    Solution

    第一问很明显,是动态规划

    先把每个导弹排序后,f[i]表示拦截最后一颗导弹为i的最大拦截数

    f[i]=max(f[i],f[j]+1)

    那么对于第二问,就要换个思路

    我们可以想,在系统拦截一个导弹i后,再拦截一个导弹j,点i向j连一条有向边

    这样就形成了有向无环图(DAG)

    所以问题转化成了求有向图的最小覆盖

    有多少条不相交的边可以覆盖整张图)

    可以把原来的一个点拆成两个点(一个为入点,一个为出点)

    总共分别有n个入点和n个出点形成了二分图

    所以我们只需要把二分图的最大匹配ans求出来,最后把n-ans即是答案

    这里我选择了匈牙利算法(其他做法也许可以),机子跑得快

    要注意最好用位运算符,速度快,不然有可能过不了,我试过了

    代码如下:

    //blog:https://www.cnblogs.com/yjyl0098/
    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 1000+50
    int ans;
    int q[maxn<<1][maxn];
    int f[maxn<<1];
    bool judge[maxn<<1];
    struct yjyl
    {
        int x,y,z;
    }a[maxn];
    
    inline bool cmp(yjyl x,yjyl y)
    {
        return x.x<y.x;
    }
    inline int read()
    {
        int X=0,w=1;
        char ch=0;
        while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
        return X*w;
    }
    inline int max(int x,int y)
    {
        return x>y?x:y;
    }
    inline int  Hg(int x)
    {
        for(int i=1;i<=q[x][0];i++)
            if(!judge[q[x][i]])
            {
                judge[q[x][i]]=1;
                if(!f[q[x][i]]||Hg(f[q[x][i]]))
                {
                    f[q[x][i]]=x;
                    return 1;
                }
            }
        return 0;
    }//把一个点拆成两个点,跑匈牙利算法
    int main()
    {
        freopen("missile.in","r",stdin);
        freopen("missile.out","w",stdout);
        int n=read();
        for(int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),a[i].z=read();
        sort(a+1,a+n+1,cmp);
        for(int i=1;i<=n;i++)
            for(int j=f[i]=1;j<i;j++)
                if(a[i].y>a[j].y&&a[i].z>a[j].z)
                {
                    f[i]=max(f[i],f[j]+1);//动态规划
                    q[j<<1][++q[j<<1][0]]=i<<1|1;
                }
        for(int i=1;i<=n;i++)
        {
            if(f[i]>ans) ans=f[i];
            f[i]=0;
        }
        printf("%d
    ",ans),ans=0;
        for(int i=2;i<=n<<1;i+=2)
        {
            memset(judge,0,sizeof(judge));
            if(Hg(i)!=0) ans++;//ans求的就是最大匹配数
        }
        printf("%d",n-ans);//为什么是减呢?因为多一个匹配就少一个系统
    }

    end

  • 相关阅读:
    Oracle11gR2下PL/SQL访问网络的错误ORA24247
    安装cx_Oracle
    搭建基于FreeNAS的共享存储
    unique constraint 和 unique index 的关系
    Oracle11gR2_RAC全静默安装攻略
    struts中的constant详解 (转载)
    网摘
    用 Google 的 FaceNet 做人脸识别极客帮课程笔记
    【Linux】Git 安装最新版
    【Jmeter】性能测试EMQ X 压测
  • 原文地址:https://www.cnblogs.com/yjyl0098/p/13458440.html
Copyright © 2011-2022 走看看