更木棒的阅读体验 /se \to→George1123


题面

NOI2003 智破连环阵

有 mm 个靶子 (ax_j,ay_j)(axj​,ayj​) 和 nn 个箭塔 (bx_i,by_i)(bxi​,byi​)。每个箭塔可以射中距离在 kk 以内的靶子。第 i+1i+1 只有第 ii 个靶子被射中时才能被射中。每个箭塔只能用一次,现在可以安排每个箭塔的射击顺序,求最少需要几个箭塔可以射光 mm 靶子。

数据范围:1\le m,n\le 1001≤m,n≤100,1\le k\le 10001≤k≤1000,1\le ax_j,ay_j,bx_i,by_i\le 100001≤axj​,ayj​,bxi​,byi​≤10000。


蒟蒻语

爆搜神题,可惜题解都很晦涩,蒟蒻因为一个小错误折腾了一个晚上,现在拿到了最优解,于是准备写个逊逊的题解。


蒟蒻解

首先每个箭塔解决一个靶子区间。

所以可以爆搜每个区间和箭塔匹配,这很明显是个二分图匹配。

为了方便处理很多细节,设所有 ii 为箭塔的下标,jj 为靶子的下标。

设 bool con_{i,j}coni,j​ 表示箭塔 ii 与靶子 jj 联通。

由于每个箭塔的每个负责区间只需用后缀就可以有解,所以记录 nex_{i,j}nexi,j​ 表示箭塔 ii 在靶子 jj 后面第一个射不到的靶子(即可用射到最右边的靶子下标 +1+1)。

// 这是一个很显然的递推
R(i,0,n)L(j,0,m) con[i][j]&&(nex[i][j]=max(j+1,nex[i][j+1]));

为了后面 A* 做准备,还可以求出一个 mn_jmnj​ 表示打到靶子 jj 的剩余步数下限。

L(j,0,m)R(i,0,n) con[i][j]&&(mn[j]=min(mn[j],mn[nex[i][j]]+1));

然后就可以开始惊心动魄的 Dfs 了。

最直接的方法是先用 mn_jmnj​ 来剪枝 A* 一下,然后用 nex_{i,j}nexi,j​ 枚举下一个区间端点,用过的箭塔打个标记,匹配一个没用过的箭塔。

前文说过这是个二分图匹配,所以有个野蛮操作(二分图优化):每次区间找好后,直接匈牙利匹配看看能不能匹配得到箭塔。

这个操作时间复杂度比起原来操作是不增的。

但是这有什么用呢?要配上另一个骚操作:逆序枚举下一个区间开始端点。

由于用了匈牙利后完美匹配概率变高,所以就可以尽早找到优的答案,进一步 A* 剪枝。

然后就结束了,时限 2s2s 的题跑得最慢的点 4ms4ms,总时间 31ms31ms。

注意 Dfs 回溯算法两个坑:回溯不彻底、回溯用了全局变量。


代码

#include <bits/stdc++.h>
using namespace std;//Start
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair((a),(b))
#define x first
#define y second
#define be(a) (a).begin()
#define en(a) (a).end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define R(i,a,b) for(int i=(a),I=(b);i<I;i++)
#define L(i,a,b) for(int i=(b)-1,I=(a)-1;i>I;i--)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;/*
注意: i 是箭塔,j 是靶子,s 是区间
*///Data
const int N=1e2;
int m,n,k;
pair<int,int> a[N],b[N];
bitset<N> con[N];
#define f(x) ((x)*(x))//Dfs
bitset<N> e[N],vis;
int nex[N][N+1],mn[N+1],mat[N],ans;
bool match(int s){ // 匈牙利匹配R(i,0,n)if(e[s][i]&&!vis[i]){vis[i]=true;if(!~mat[i]||match(mat[i]))    return mat[i]=s,true;}return false;
}
void dfs(int j,int s){if(ans<=s+mn[j]) return; //A*if(j==m) return void(ans=s);int cmat[N]; copy(mat,mat+n,cmat); // 这里的 cmat 你要是设为全局变量就死了,我在这里死了 2 个小时L(J,j+1,m+1){R(i,0,n) con[i][j]&&nex[i][j]>=J&&(e[s][i]=true);R(i,0,n) vis[i]=false; match(s)?dfs(J,s+1):void();R(i,0,n) con[i][j]&&nex[i][j]>=J&&(e[s][i]=false); //莫忘回溯copy(cmat,cmat+n,mat);}
}//Main
int main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);cin>>m>>n>>k;R(j,0,m) cin>>a[j].x>>a[j].y;R(i,0,n) cin>>b[i].x>>b[i].y;R(i,0,n)R(j,0,m) con[i][j]=(f(a[j].x-b[i].x)+f(a[j].y-b[i].y)<=f(k));R(i,0,n) fill(nex[i],nex[i]+m+1,-1);R(i,0,n)L(j,0,m) con[i][j]&&(nex[i][j]=max(j+1,nex[i][j+1]));R(j,0,m) mn[j]=iinf;L(j,0,m)R(i,0,n) con[i][j]&&(mn[j]=min(mn[j],mn[nex[i][j]]+1));fill(mat,mat+n,-1),ans=min(n,m),dfs(0,0);// 夹杂点骚操作(正确性不保证,仅用来抢最优解:猜测最终 ans<=mn[0]+5),把 ans 的初始值和 mn[0]+5 取 mincout<<ans<<'\n';return 0;
}

祝大家学习愉快!

P1526 [NOI2003] 智破连环阵 题解相关推荐

  1. NOI2003 智破连环阵

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

  2. [NOI2003]智破连环阵

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

  3. 洛谷 P1562 智破连环阵 题解(搜索)

    传送门 根据勾股定理: 一个武器 (x,y)(x,y)(x,y) 能被炸弹 (u,v)(u,v)(u,v) 攻击到 ⇔(x−u)2+(y−v)2<=k2\Leftrightarrow (x-u) ...

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

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

  5. 【NOI2003】智破连环阵

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

  6. 洛谷P1526 智破连环阵

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

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

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

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

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

  9. XDU Problem 1037 - 智破机枪阵

    裸的最大二分匹配,匈牙利算法 #include<iostream> #include<cstdio> #include<cstring> #include<c ...

最新文章

  1. 莫比乌斯函数+莫比乌斯反演
  2. 欧洲打击洗钱 全球联合行动 178名钱骡落网
  3. Tomcat 8熵池阻塞变慢详解
  4. 与张小龙同行:微信小程序开发
  5. python怎么计算时间_python怎么计算若干分钟后是第几天,星期几
  6. Basler相机SDK相关问题收集与知识汇总
  7. Ice_cream's world I HDU - 2120(并查集判环)
  8. 微软启动了自爆程序,让我们一起帮它倒计时
  9. 二维码研究综述--传统图像处理方法
  10. java怎样生成32位全是整形的主键_用java生成32位全球唯一的id编号
  11. SolarWinds 攻击者开发的新后门 FoggyWeb
  12. oracle如何调试sql,调试oracle与调试sql server存储过程
  13. 懵圈了,面试官问一个 TCP 连接可发多少个 HTTP 请求?
  14. 拓端tecdat|R语言聚类有效性:确定最优聚类数分析IRIS鸢尾花数据和可视化
  15. Carrot2对文章进行聚类代码示例
  16. 微软认证-新的MCSE和MCSA考试详解
  17. 01 你了解依赖倒置原则吗
  18. 翻炒《天龙八部》[转]
  19. 计算机ppt以学校生活为主题的作文,以校园为主题的作文(通用5篇)
  20. exsi 无法打开虚拟机 执行此操作的权限被拒绝[解决]

热门文章

  1. win7怎么看计算机显卡内存大小,Win7系统怎么看显存?
  2. 5G基站到底长啥样?和4G有啥区别?
  3. 从零开始学习Java设计模式 | 软件设计原则篇:依赖倒转原则
  4. 前端优化中的防抖与截流
  5. Codeforces 480D Parcels(dp)
  6. android 获得屏幕方向,Android 获取设置屏幕横竖屏
  7. 完美解决:“已损坏,无法打开。 您应该将它移到废纸篓。”
  8. GDI+ 中图片的绘制
  9. Grad-CAM:Visual Explanations from Deep Networks via Gradient-based Localization
  10. 启动jupyter notebook链接不上内核 + 终端报错:Replacing stale connection