zoukankan      html  css  js  c++  java
  • 【bzoj2044】三维导弹拦截 dp+二分图最大匹配

    题目描述

    n个物品,第i个位置有ai、bi、ci三种属性。每次可以选出满足$ a_{p_i}<a_{p_{i+1}} , b_{p_i}<b_{p_{i+1}} , c_{p_i}<c_{p_{i+1}} $的一段序列$p_1,p_2,...,p_k$(不要求$p_1,p_2,...,p_k$的大小关系),将这些物品$p_i$消掉。问:(1)一次最多能够消掉的物品的数目。 (2)最少需要多少次操作能够把所有物品全部消掉。

    输入

    第一行一个整数N给出B国导弹的数目。 接下来N行每行三个非负整数Xi, Yi, Zi给出一个导弹的位置,你可以假定任意两个导弹不会出现在同一位置。

    输出

    第一行输出一个整数P,表示一枚拦截导弹之多能够摧毁的导弹数。 第二行输出一个整数Q,表示至少需要的拦截导弹数目。

    样例输入

    4
    0 0 0
    1 1 0
    1 1 1
    2 2 2

    样例输出

    3
    2


    题解

    dp+二分图最大匹配

    第一问按照第一维排序,然后$n^2$暴力求二维LIS即可。

    第二问如果把能够先打A后打B的A向B连边,那么显然这是一个DAG图,我们要求的是它的最小路径覆盖。

    这是经典的二分图建模了,说一下做法吧:

    每个原图中的点拆成两个($A_i$和$A_j$),如果存在边$A o B$,则连边$A_i o B_j$。跑二分图最大匹配,n-最大匹配即为答案。

    于是直接上匈牙利算法/dinic即可。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 1010
    using namespace std;
    struct data
    {
    	int a , b , c;
    	bool operator<(const data x)const {return a < x.a;}
    }v[N];
    int f[N] , head[N] , to[N * N] , next[N * N] , cnt , vis[N] , from[N];
    inline void add(int x , int y)
    {
    	to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
    }
    bool dfs(int x)
    {
    	int i;
    	for(i = head[x] ; i ; i = next[i])
    	{
    		if(!vis[to[i]])
    		{
    			vis[to[i]] = 1;
    			if(!from[to[i]] || dfs(from[to[i]]))
    			{
    				from[to[i]] = x;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    int main()
    {
    	int n , i , j , ans1 = 0 , ans2 = 0;
    	scanf("%d" , &n);
    	for(i = 1 ; i <= n ; i ++ ) scanf("%d%d%d" , &v[i].a , &v[i].b , &v[i].c);
    	sort(v + 1 , v + n + 1);
    	for(i = 1 ; i <= n ; i ++ )
    	{
    		f[i] = 1;
    		for(j = 1 ; j < i ; j ++ )
    			if(v[j].a < v[i].a && v[j].b < v[i].b && v[j].c < v[i].c)
    				f[i] = max(f[i] , f[j] + 1) , add(j , i);
    		ans1 = max(ans1 , f[i]);
    	}
    	printf("%d
    " , ans1);
    	for(i = 1 ; i <= n ; i ++ )
    	{
    		memset(vis , 0 , sizeof(vis));
    		if(dfs(i)) ans2 ++ ;
    	}
    	printf("%d
    " , n - ans2);
    	return 0;
    }
    

     

  • 相关阅读:
    NodeJs操作MongoDB之分页功能与常见问题
    NodeJs之word文件生成与解析
    NodeJs之EXCEL文件导入导出MongoDB数据库数据
    NodeJs之文件上传
    NodeJs之定时器与队列
    NodeJs操作MongoDB之多表查询($lookup)与常见问题
    Windows下安装配置MongoDB
    关于fastJson的几个问题
    (转)java并发编程:CopyOnWriteArrayList
    java并发编程:锁的相关概念介绍
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7600349.html
Copyright © 2011-2022 走看看