热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

bzoj4622[NOI2003]智破连环阵

DescriptionB国在耗资百亿元之后终于研究出了新式武器——连环阵(ZenithProtectedLinkedHybridZone)。传说中,连环阵是一种永不停滞

Description

B国在耗资百亿元之后终于研究出了新式武器——连环阵(Zenith Protected Linked Hybrid Zone)。传说中,连环阵是一种永不停滞的自发性智能武器。但经过A国间谍的侦察发现,连环阵其实是由M个编号为1,2,…,M的独立武器组成的。最初,1号武器发挥着攻击作用,其他武器都处在无敌自卫状态。以后,一旦第i(1<=i

Input

第一行包含三个整数:M、n和k(1<=M, n<=100,1<=k<=1000),分别表示B国连环阵由M个武器组成,A国有n个炸弹可以使用,炸弹攻击范围为k。以下M行,每行由一对整数xi,yi(0<=xi,yi<=10000)组成,表示第i(1<=i<=M)号武器的平面坐标。再接下来n行,每行由一对整数ui,vi(0<=ui,vi<=10000)组成,表示第i(1<=i<=n)号炸弹的平面坐标。输入数据保证随机、无误、并且必然有解。

Output

一行包含一个整数x,表示实际使用的炸弹数.

Sample Input

Sample Input 1
4 3 6
0 6
6 6
6 0
0 0
1 5
0 3
1 1

Sample Input 2
10 10 45
41 67
34 0
69 24
78 58
62 64
5 45
81 27
61 91
95 42
27 36
91 4
2 53
92 82
21 16
18 95
47 26
71 38
69 12
67 99
35 94

Sample Output

Sample Output 1
2

Sample Output 2
5
HINT
输出数据为NOI原数据
输出数据由楼教主代码制作
原题有spj 此题去掉spj 只输出最优解

HINT 

 NOI2003 Day2 T3  感谢sxb_201上传

 

正解:搜索+$dp$+二分图最大匹配。

丧心病狂的$zjo$竟然把这题出成考试题。。我敢说这是我见过的最玄学的搜索题。。

首先,我们发现每个炸弹肯定炸一段连续的区间。那么有一个很直观的暴力的思路,那就是枚举区间。对于每个区间,能够完全覆盖的炸弹向它连边,跑一遍二分图最大匹配就行了。

这样显然是过不了的,所以我们要剪枝。我们假设每个炸弹可以重复使用,那么我们算出当前武器开始的所有武器最少还需几个炸弹才能消灭。

这个用$dp$来预处理。设$can[p][i][j]$表示$p$号炸弹,是否能够炸$[i,j]$这个区间。那么设$dis[i]$表示炸$[i,m]$需要的最少炸弹,易知$dis[i]=min(dis[j]+1)$,$i

最优性剪枝:$now+dis[i]>=ans$则剪枝,$now$为当前炸弹数。

可行性剪枝:我们可以每次直接在原图的基础上进行增广,如果当前点不能进行增广,就不用再往下搜索了。

然而这些剪枝还是不足以通过全部数据,我们不妨从可行性剪枝上入手。

我们可以尝试求出当前区间右端点的最大值$maxl$,那么显然,$maxl$及其之前的端点都是可行的。

我们发现这样可以很大程度地优化时间。首先,我们可以从$maxl$到$l$依次枚举右端点,减少搜索量;其次,我们可以只进行一次增广,因为$can[p][i][j]>=can[p][i][j+1]$,那么右端点为$maxl$时连的边,在右端点减小时同样也会出现,并不会影响答案。

如何求出$maxl$?首先我们要求出辅助数组$maxt[p][l]$,表示炸弹$p$从$l$开始能炸到的最远的点的编号,这个很容易预处理出来,就不再赘述。

注意到匈牙利算法的过程,一个炸弹能够使用有两种情况。首先是这个炸弹没有出现在匹配边上;其次是这个炸弹虽然出现在匹配边上,但是它能够通过增广以后和当前区间匹配。那么我们就可以使用$bfs$来解决这个问题,求出所有能够使用的炸弹(具体操作看代码吧。。),然后不断地取$maxt[p][l]$的最大值,就能求出$maxl$了。

这就是本题的两个重要剪枝,加上这两个剪枝以后极限数据也可以瞬间求解了。

 

 1 //It is made by wfj_2048~
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include <set>
13 #define inf (1<<30)
14 #define N (110)
15 #define il inline
16 #define RG register
17 #define ll long long
18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
19
20 using namespace std;
21
22 int can[N][N][N],maxt[N][N],g[N][N],dis[N],vis[N],lk[N],mt[N],x[N],y[N],u[N],v[N],q[N],n,m,k,cnt,ans;
23
24 il int gi(){
25 RG int x=0,q=1; RG char ch=getchar();
26 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
27 if (ch=='-') q=-1,ch=getchar();
28 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
29 return q*x;
30 }
31
32 il void pre(){
33 for (RG int i=1;i<=m;++i) x[i]=gi(),y[i]=gi();
34 for (RG int i=1;i<=n;++i){
35 u[i]=gi(),v[i]=gi();
36 for (RG int j=1;j<=m;++j)
37 g[i][j]=(u[i]-x[j])*(u[i]-x[j])+(v[i]-y[j])*(v[i]-y[j])<=k*k;
38 }
39 for (RG int p=1;p<=n;++p){
40 for (RG int i=1;i<=m;++i) can[p][i][i]=g[p][i],maxt[p][i]=g[p][i]?i:i-1;
41 for (RG int i=1;ii)
42 for (RG int j=i+1;j<=m;++j){
43 can[p][i][j]=can[p][i][j-1]&g[p][j];
44 if (can[p][i][j]) maxt[p][i]=j;
45 }
46 }
47 for (RG int i=m;i;--i){
48 dis[i]=inf;
49 for (RG int j=i;j<=m;++j)
50 for (RG int p=1;p<=n;++p)
51 if (can[p][i][j]) dis[i]=min(dis[i],dis[j+1]+1);
52 }
53 return;
54 }
55
56 il int hungry(RG int x){
57 for (RG int v=1;v<=n;++v){
58 if (!g[x][v] || vis[v]==cnt) continue; vis[v]=cnt;
59 if (!lk[v] || hungry(lk[v])){ mt[x]=v,lk[v]=x; return 1; }
60 }
61 return 0;
62 }
63
64 il void dfs(RG int l,RG int id){
65 if (l>m){ ans=id-1; return; } if (id-1+dis[l]>=ans) return;
66 ++cnt; RG int LK[N],MT[N],h=0,t=0,maxl=l-1;
67 for (RG int i=1;i<=n;++i) if (!lk[i]) vis[i]=cnt,q[++t]=i;
68 while (h<t){
69 RG int x=q[++h]; maxl=max(maxl,maxt[x][l]);
70 for (RG int i=1;ii)
71 if (g[i][x] && vis[mt[i]]!=cnt) vis[mt[i]]=cnt,q[++t]=mt[i];
72 }
73 memcpy(LK,lk,sizeof(LK)),memcpy(MT,mt,sizeof(MT));
74 for (RG int i=1;i<=n;++i) g[id][i]=can[i][l][maxl]; ++cnt,hungry(id);
75 for (RG int r=maxl;r>=l;--r){
76 for (RG int i=1;i<=n;++i) g[id][i]=can[i][l][r]; dfs(r+1,id+1);
77 }
78 memcpy(lk,LK,sizeof(lk)),memcpy(mt,MT,sizeof(mt)); return;
79 }
80
81 il void work(){
82 m=gi(),n=gi(),k=gi(),pre(),ans=n;
83 dfs(1,1),printf("%d\n",ans); return;
84 }
85
86 int main(){
87 File("boom");
88 work();
89 return 0;
90 }

 


推荐阅读
  • 一文了解Python collections模块中的deque用法[python头条资讯]
    Python中文网有大量免费的Python入门教程,欢迎大家来学习。collections是Python内建的一个集合模块,deque是双边队列,具有队列和栈的性质,在list的基 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • 题目描述Takuru是一名情报强者,所以他想利用他强大的情报搜集能力来当中间商赚差价。Takuru的计划是让Hinae帮他去市场上买一个商品,然后再以另一个价格卖掉它。Takur ... [详细]
  • DescriptionclickmeSolution套路的状压期望DP题。。。考虑倒退期望:设fi,jrolepresentationstyleposi ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • C++ STL复习(13)容器适配器
    STL提供了3种容器适配器,分别为stack栈适配器、queue队列适配器以及priority_queue优先权队列适配器。不同场景下,由于不同的序列式 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
author-avatar
瓜瓜哥哥
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有