传送门


根据勾股定理:

一个武器 (x,y)(x,y)(x,y) 能被炸弹 (u,v)(u,v)(u,v) 攻击到 ⇔(x−u)2+(y−v)2<=k2\Leftrightarrow (x-u)^2+(y-v)^2<=k^2⇔(x−u)2+(y−v)2<=k2

通过这个条件,对每个炸弹求出一个 mmm 位的 bitset 表示范围内武器集合。


我们考虑简化摧毁武器的过程,发现每次都是摧毁一段连续区间内的武器。即:将 mmm 个武器分成若干个连续区间,按顺序每次摧毁其中 111 个。

那么就想到搜索。搜索区间的划分方案。

  • dfs(i,cnt,lst)dfs(i,cnt,lst)dfs(i,cnt,lst) 表示考虑到第 iii 个位置,当前区间左端点是 lstlstlst,lstlstlst 之前划分了 cntcntcnt 个区间的最小答案。
  • 每次考虑当前是否开一个新区间,转移到 dfs(i+1,cnt,lst)dfs(i+1,cnt,lst)dfs(i+1,cnt,lst) 和 dfs(i+1,cnt+1,i+1)dfs(i+1,cnt+1,i+1)dfs(i+1,cnt+1,i+1)。

考虑对于一个区间划分方案,每个区间都对应一个唯一的炸弹。那么可以将 nnn 个炸弹和 cntcntcnt 个区间看作节点。若炸弹可以摧毁一个区间,则两者连边,构造二分图。若:二分图最大匹配数 = cntcntcnt,那么这个区间划分方案就是合法的,使用炸弹个数 = cntcntcnt。

对于二分图的匹配,我们用匈牙利算法解决。这里就不解释匈牙利算法了,可以自行搜索。 在搜索的同时,每次新开一个区间 [lst,i][lst,i][lst,i],就用匈牙利算法去找是否存在炸弹可以和这个区间匹配。如果是,就可以转移。最后答案就是最小区间个数。


以上是搜索的思路,在实现时还要加入优化。

  1. 可以提前 O(nm2)O(nm^2)O(nm2) 预处理,对于每个区间 [l,r][l,r][l,r],包含 [l,r][l,r][l,r] 的炸弹列表。若当前要将 [lst,i][lst,i][lst,i] 划成一个区间,在二分图上就对应这个列表里的所有炸弹,实时匈牙利算法 check 一下,如果 check⁡(lst,i)=false\operatorname{check}(lst,i)=falsecheck(lst,i)=false,那么就剪枝。因为当前 [lst,i][lst,i][lst,i] 无法匹配,说明后面 [lst,i+j],∀0<=j<=m−i[lst,i+j],\forall{0<=j<=m-i}[lst,i+j],∀0<=j<=m−i 也一定无法匹配。不存在合法方案。

  2. A* 剪枝,倒序预处理 mn[1...m]mn[1...m]mn[1...m],表示从 iii 开始,[i,m][i,m][i,m] 这个区间内所有武器最小要用几个炸弹爆破(相同炸弹可以多次使用)。可以 O(m2)O(m^2)O(m2) 暴力预处理 mnmnmn 数组,dfs 时若 cnt+mn[lst]>=anscnt+mn[lst]>=anscnt+mn[lst]>=ans,其中 ansansans 表示当前最优答案。说明答案不会更优,进行最优性剪枝。

  3. 每个 dfs 状态,如果 check⁡(lst,i)=true\operatorname{check}(lst,i)=truecheck(lst,i)=true,可以转移,那么先搜索 dfs(i+1,cnt,lst)dfs(i+1,cnt,lst)dfs(i+1,cnt,lst),再搜索 dfs(i+1,cnt+1,i+1)dfs(i+1,cnt+1,i+1)dfs(i+1,cnt+1,i+1),这样更容易先搜到最优答案。

加上这些优化后就能高效地 水过 通过。


Code

#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
#define F first
#define S second
using namespace std;
int n,m,K,x[205],y[205],to[105][105],mn[105],ans;//to表示二分图匹配中区间对应的炸弹
pii mch[105];//炸弹在二分图匹配中对应的区间
bitset<105> a[105];
vector<int> v[105][105];
bool used[105],link[105][105];
bool check(int l,int r,bool f=1)//匈牙利算法核心代码
{if (f)//初始化used数组fill(used,used+m,0);for(auto u:v[l][r])if (!used[u]){used[u]=1;if (mch[u].F==-1||check(mch[u].F,mch[u].S,0))//如果当前炸弹没有用过或其对应的区间可以用别的炸弹处理,则可以用这个炸弹处理当前区间[l,r]{mch[u]=mp(l,r);to[l][r]=u;return 1; }}return 0;
}
void dfs(int i,int cnt,int lst)
{if (i==n-1){if (check(lst,i)){ans=min(ans,cnt+1);mch[to[lst][i]]=mp(-1,-1);}return;}if (cnt+mn[lst]>=ans)//A*最优性剪枝return;if (check(lst,i))//可以转移{mch[to[lst][i]]=mp(-1,-1);dfs(i+1,cnt,lst);//不新增区间}if (check(lst,i)){dfs(i+1,cnt+1,i+1);//新增区间mch[to[lst][i]]=mp(-1,-1);//回溯}
}
int main()
{ios::sync_with_stdio(false),cin.tie(nullptr);cin>>n>>m>>K;//代码n和m的定义与题面相反for(int i=0;i<n+m;i++)cin>>x[i]>>y[i];for(int i=0;i<m;i++)for(int j=0;j<n;j++)if ((x[n+i]-x[j])*(x[n+i]-x[j])+(y[n+i]-y[j])*(y[n+i]-y[j])<=K*K)a[i][j]=1;//处理bitsetfor(int i=0;i<m;i++)//预处理区间[l,r]可以对应的炸弹列表{for(int l=0;l<n;l++)  for(int r=0;r<n;r++)link[l][r]=0;for(int l=0;l<n;l++)if (a[i][l]){link[l][l]=1;v[l][l].pb(i);}for(int r=1;r<n;r++)for(int l=r-1;l>=0;l--)if (link[l][r-1]&&a[i][r]){link[l][r]=1;v[l][r].pb(i);}}for(int i=n-1,j=n-1,cnt=0;i>=0;i--)//预处理mn数组{while(j>=i){int p=j;while(p>=0&&!v[p][j].empty())//贪心,每次取可能大的区间覆盖当前位置--p;j=p;++cnt;}mn[i]=cnt;}memset(mch,-1,sizeof(mch));memset(to,-1,sizeof(to));ans=m;dfs(0,0,0);cout<<ans<<endl;return 0;
}

洛谷 P1562 智破连环阵 题解(搜索)相关推荐

  1. 洛谷P1526 智破连环阵

    题目描述 B 国在耗资百亿元之后终于研究出了新式武器--连环阵(Zenith Protected Linked Hybrid Zone).传说中,连环阵是一种永不停滞的自发性智能武器.但经过 A 国间 ...

  2. P1526 [NOI2003] 智破连环阵 题解

    更木棒的阅读体验 /se \to→George1123 题面 NOI2003 智破连环阵 有 mm 个靶子 (ax_j,ay_j)(axj​,ayj​) 和 nn 个箭塔 (bx_i,by_i)(bx ...

  3. NOI2003 智破连环阵

    先甩两个论文: 这是楼教主的 用的 部分搜索 + 匹配   代码飞快比较神 算法合集之<浅谈部分搜索+高效算法在搜索问题中的应用 这是朱泽园的算是 面向数据编程..  用的 贪心搜索+各种剪枝( ...

  4. 【21.00%】【vijos P1018】智破连环阵

    描述 B国在耗资百亿元之后终于研究出了新式武器--连环阵(Zenith Protected Linked Hybrid Zone).传说中,连环阵是一种永不停滞的自发性智能武器.但经过A国间谍的侦察发 ...

  5. 【NOI2003】智破连环阵

    题目描述 B国在耗资百亿元之后终于研究出了新式武器--连环阵(Zenith Protected Linked Hybrid Zone).传说中,连环阵是一种永不停滞的自发性智能武器.但经过A国间谍的侦 ...

  6. [NOI2003]智破连环阵

    题目大意:给出地图上N个目标点,M台武器(只能用一次).每个武器启动后,将距它距离不超过K范围内的符合要求的目标全部摧毁(符合要求:摧毁目标必须按编号顺序,而且同一时刻只有一个武器是启动的),求摧毁全 ...

  7. BZOJ4622 [NOI 2003] 智破连环阵

    题面 题意 有n个点需要被覆盖,你有m个半径为k的圆,每个圆覆盖的点是圆内(包括边界)编号连续的一些点,且每个圆只能使用一次,问至少要选择几个圆才能覆盖所有点. 做法 这个问题可以拆成两个子问题: 1 ...

  8. COGS 336 Vijos 1018 NOI2003 智破连环阵

    楼教主论文里的题 这么多剪枝吓坏我了 忽然想起来我WC的时候第一题前两个点也是搜索+最大流,不知道能不能剪枝把后面的数据水过去呢233333然而并不能想到什么剪枝 #include<iostre ...

  9. 洛谷P5520 [yLOI2019] 青原樱 题解

    洛谷P5520 [yLOI2019] 青原樱 题解 题目链接:P5520 [yLOI2019] 青原樱 题意: n n n 个空放 m m m 个物品,两两物品不能直接相邻,至少空一格 纯数学题. 看 ...

最新文章

  1. 曼尼托巴大学计算机硕士录取要求,曼尼托巴大学硕士
  2. apache ab压力测试报错apr_socket_recv
  3. 什么是python函数_Python之什么是函数
  4. swift自行车品牌介绍_品牌101:简介
  5. 设置最大值_变频器用远传压力表控制恒压供水参数设置
  6. 如何用Pygame写游戏(十九)
  7. 在Unterfranken中搜索河流:如何使用Elasticsearch在地图上查找要素
  8. Android UI 优化——使用HierarchyViewer工具
  9. Servlet编写登陆页面简单实践
  10. 你知道如何计算CNN感受野吗?这里有一份详细指南
  11. Writing Serializable Classes---定义可序列化的类
  12. Unity —Spine动画
  13. Synopsys VCS vY-2006.06
  14. Java技术体系简介
  15. MagicDraw建模显示中文问题
  16. 计算机无法连接苹果手机软件,iphone连不上itunes
  17. 一键激活Win8.1、wni7\winser(无需联网)
  18. 实战教程:平面设计配色原则
  19. 闽江师范高等专科学校计算机系成立时间,闽江师范高等专科学校2018届毕业典礼...
  20. 上传webshell(入侵目标页面主机靶机演示)

热门文章

  1. 如何开发微信小程序?(入门须知)
  2. 无线网ppp服务器失败怎么办,【妙招】不能上网怎么办,史上最全宽带故障简单处理办法!...
  3. java准确读取word文件页数
  4. springboot冷链物流信息调度系统毕业设计源码210951
  5. java导出json格式化的json文件及xml文件
  6. Vue中使用防抖与截流
  7. vue中使用防抖和截流
  8. oracle 非等值关联 优化,Oracle优化器、优化模式、表的连接方式(Hash Join、Nested Loop、Sort Merge Join)...
  9. 几何分布的期望和方差公式推导_算法数学基础-统计学最基础之均值、方差、协方差、矩...
  10. Image Pro Plus6进行荧光分析与荧光照片合成学习笔记