《Yuchang and Zixiang’s stones》
时间:2021-08-24
本文章向大家介绍《Yuchang and Zixiang’s stones》,主要包括《Yuchang and Zixiang’s stones》使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题意:简化下就是给定一个n * m的棋盘,有q组询问,每次询问棋子是否能放置在该位置。
能放置的条件就是,该位置之前没棋子,且该位置可以走到棋盘外。
Solution:
很明显这里是一个搜索类的问题,但是因为询问次数过多,如果对于每次询问都去搜索显然会超时。
考虑对询问离线:假定我们目前已经放置下了所有的棋子,并且处理出此时哪些位置可以走出棋盘外,哪些不能。然后我们倒序回去拆棋子。
当我们去拆这个棋子时,我们去查询它周围的点,是否可以走到棋盘外,若没有点可以,我们拆不拆除这个点都没有影响。
若周围有点可以,显然拆除后这个点也可以,那么我们拆除该点。
同时从这个点开始搜索,去更新之前无法走到,但是拆除这个点后可以走到的点。
基于上诉思路,可以发现每个点基本只会更新一次,那么时间复杂度平摊后为O(棋子数)。
可以发现此题可能存在一个点放置多次的情况,即我们回去处理的时候可能一个点处理多次,这个时候我只要去处理第一次放置这个位置的情况即可。
以下是这样处理的证明:
对于一个位置,如果它第一次放置时,就无法放置,那么显然后面再想去放置这个点更不可能可以放置,所以如果它不能放置,那么后面放置时都不会产生影响。
如果一个位置可以放置,那么当他放置后,这个位置后序将再无法放置,且很显然若这个位置可以放置,那么他放置的时间一定是最早的时间,所以对于第一次之后的放置。
也不会对结果产生影响。故只需要去最前面一次进行处理即可。
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef __int128_t BIG; typedef pair<int,int> pii; const int N = 1e6 + 5; const int M = 1e3 + 5; const double eps = 1e-10; const LL Mod = 4294967296; #define pi acos(-1) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; int n,m,b[4][2] = {1,0,-1,0,0,1,0,-1}; int vis[M][M]; bool isget[M][M]; void Prework() { queue<pii> Q; memset(isget,0,sizeof(isget)); for(int i = 1;i <= n;++i) { if(vis[i][1] == INF) { isget[i][1] = 1; Q.push(pii{i,1}); } if(vis[i][m] == INF) { isget[i][m] = 1; Q.push(pii{i,m}); } } for(int i = 1;i <= m;++i) { if(vis[1][i] == INF) { isget[1][i] = 1; Q.push(pii{1,i}); } if(vis[n][i] == INF) { isget[n][i] = 1; Q.push(pii{n,i}); } } while(!Q.empty()) { pii q = Q.front(); Q.pop(); for(int i = 0;i < 4;++i) { int px = q.first + b[i][0]; int py = q.second + b[i][1]; if(px >= 1 && px <= n && py >= 1 && py <= m && isget[px][py] == 0 && vis[px][py] == INF) { isget[px][py] = 1; Q.push(pii{px,py}); } } } } bool isdir(int i,int j) { if(i == 1 || i == n || j == 1 || j == m) return true; for(int k = 0;k < 4;++k) { int px = i + b[k][0]; int py = j + b[k][1]; if(px >= 1 && px <= n && py >= 1 && py <= m && isget[px][py] == 1) return true; } return false; } void cal(int sx,int sy,int id) { queue<pii> Q; Q.push(pii{sx,sy}); while(!Q.empty()) { pii q = Q.front(); Q.pop(); for(int i = 0;i < 4;++i) { int px = q.first + b[i][0]; int py = q.second + b[i][1]; if(px >= 1 && px <= n && py >= 1 && py <= m && isget[px][py] == 0 && vis[px][py] > id) { isget[px][py] = 1; Q.push(pii{px,py}); } } } } bool isu[M][M],tag[M][M]; int sum = 0,f = 0; void dfs(int x,int y) { if(f) return ; if(x == 1 || x == n || y == 1 || y == m) f = 1; if(!tag[x][y]) { tag[x][y] = 1; for(int i = 0;i < 4;++i) { int px = x + b[i][0]; int py = y + b[i][1]; if(px >= 1 && px <= n && py >= 1 && py <= m && isu[px][py] == 0) dfs(px,py); } } } bool solve2(int sx,int sy) { f = 0; memset(tag,0,sizeof(tag)); dfs(sx,sy); return f; } int x[N],y[N]; void solve() { while(~scanf("%d %d",&n,&m)) { int q;scanf("%d",&q); for(int i = 1;i <= n;++i) for(int j = 1;j <= m;++j) vis[i][j] = INF; for(int i = 1;i <= q;++i) { scanf("%d %d",&x[i],&y[i]); /* if(solve2(x[i],y[i]) && isu[x[i]][y[i]] == 0) { printf("%d is put\n",i); sum++; isu[x[i]][y[i]] = 1; }*/ vis[x[i]][y[i]] = min(i,vis[x[i]][y[i]]); } Prework(); int ans = 0; for(int i = q;i >= 1;--i) { int dx = x[i],dy = y[i]; if(i > vis[dx][dy]) continue; if(isdir(dx,dy)) { ans++; isget[dx][dy] = 1; cal(dx,dy,i); } } printf("%d\n",ans); } } int main() { solve(); // system("pause"); return 0; }
原文地址:https://www.cnblogs.com/zwjzwj/p/15180978.html
- C语言第四讲,typedef 关键字,以及作用域
- C语言第三讲,基本数据类型
- 64位内核第二讲,进程保护之对象钩子
- x64内核HOOK技术之拦截进程.拦截线程.拦截模块
- Spring开启方法异步执行
- 64位内核第一讲,和32位内核的区别
- Maven精选系列--发布jar包到Nexus私库
- 《SpringMVC从入门到放肆》五、SpringMVC配置式开发(处理器适配器)
- 《SpringMVC从入门到放肆》四、SpringMVC配置式开发(处理器映射器)
- 什么是Spring Boot?
- 《SpringMVC从入门到放肆》三、DispatcherServlet的url-pattern配置详解
- 《SpringMVC从入门到放肆》二、SpringMVC的执行流程及默认配置
- 《SpringMVC从入门到放肆》一、概述
- Spring import配置文件使用占位符
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 如何将自定义XML视图注入SAP Fiori Elements应用
- SAP UI5控件ID的生成逻辑原理解析
- 如何自定义SAP Spartacus店铺的界面颜色风格
- 如何自定义SAP Spartacus店铺的购物车图表css风格
- 数据库PostrageSQL-从源代码安装
- Django的中间件
- WPF 使用 Skia 绘制 WriteableBitmap 图片
- dotnet 在 UOS 国产系统上使用 MonoDevelop 创建 GTK 全平台带界面应用
- dotnet 在 UOS 国产系统上安装 MonoDevelop 开发工具
- 使用SAP Spartacus快速创建一个电商店铺网站
- 使用StackBlitz和SAP Spartacus快速创建电商店铺页面
- SAP CRM Interactive Report(交互式报表)里和服务订单相关的一些字段
- SAP S/4HANA Customer Management(CRM)模块的扩展性设计
- SAP S/4HANA Customer Management(CRM)模块的Partner模型设计
- 使用soapUI消费SAP Cloud for Customer的web service