D. Kilani and the Game 解析(裸BFS、實作)
Codeforce 1105 D. Kilani and the Game 解析(裸BFS、實作)
今天我們來看看CF1105D
題目連結
題目
給一個\(n\times m\)的地圖,地圖上有幾種格子:空地、路障、某個玩家的某些城堡。(可能有\(1\le p\le9\)個玩家)
給定一開始每個玩家至少有一個城堡,玩家照順序移動,每個玩家有自己的移動步數,求最後每個玩家能有幾個城堡。
前言
寫這題一直TLE,搞了好幾個小時才發現如果每次BFS都宣告一個新的queue,那麼可能會因為allocation的cost太大而TLE,並且還有一些其他的奇怪問題(此處不提)。總之,我們應該極力避免頻繁declare queue。
想法
顯然就是BFS,但是實作上要注意:queue中存的是\(\{vertex,剩下的步數\}\),由於我們每回合開始的時候,一定會有一些點在queue裡(上回合遺留下來的,實作上我們每回合結束時把沒有移動步數的格子放入全域變數等下回合push進queue裡),我們要同時防止其他玩家走到這一點,又要讓擁有這個格子的玩家在自己的回合時不會判斷這個格子不能走,我們有兩種實作方式:
- 在push入新格子進queue之前先把格子標示為\(visited\),BFS從新格子開始時就不要檢查是否走過了(也就是只在往外走時檢查是否走過)。 這種方法可以某種程度上縮減queue中多餘的元素數量,是比較好的方法。
- push入queue時還不會標為\(visited\)。每次從新的格子開始BFS時,除非這個格子的移動數量\(>0\),否則不要標記為\(visited\)(但是地圖上已經寫上去了)。 這種方法比較糟糕,沒什麼結構。
程式碼(法1):
const int _n=1010;
struct ele{int x,y,move;};
int t,n,m,s[11],p,mp[_n][_n],ans[11];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
queue<ele> st[11],q;
bool vis[_n][_n];
char c,a[_n][_n];
main(void) {
scanf("%d%d%d",&n,&m,&p); rep(i,1,p+1)scanf("%d",&s[i]);
rep(i,1,n+1)scanf("%s",a[i]+1);
rep(i,1,n+1)rep(j,1,m+1){
c=a[i][j];int res=c;if(c=='.')res='0'+0;if(c=='#')res='0'+10;
mp[i][j]=res-'0';
if(mp[i][j]!=0 and mp[i][j]!=10)st[mp[i][j]].push({i,j,s[mp[i][j]]}),vis[i][j]=1; if(mp[i][j]==10)vis[i][j]=1;
}
while(1){
bool OUT=1;rep(i,1,p+1){if(!st[i].empty())OUT=0;}
if(OUT)break;
rep(id,1,p+1){
while(!st[id].empty())q.push(st[id].front()),st[id].pop();
ele now;int nx,ny;
while(!q.empty()){
now=q.front(); q.pop();
int x=now.x,y=now.y,mv=now.move;
mp[x][y]=id;
if(mv==0)st[id].push({x,y,s[id]});
else rep(j,0,4){
nx=x+dx[j],ny=y+dy[j];
if(nx<1||nx>n||ny<1||ny>m||vis[nx][ny]||mp[nx][ny]||mv<=0)continue;
vis[nx][ny]=1;
q.push({nx,ny,mv-1});
}
}
}
}
rep(i,1,n+1)rep(j,1,m+1)ans[mp[i][j]]++;
rep(i,1,p+1)printf("%d ",ans[i]);
return 0;
}
標頭、模板請點Submission看
Submission
程式碼(法2):
const int _n=1010;
struct ele{int x,y,move;};
int t,n,m,s[20],p,mp[_n][_n],ans[20];
queue<ele> st[20],q;
bool vis[_n][_n];
char c;
main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
cin>>n>>m>>p;rep(i,1,p+1)cin>>s[i];
cin.get();rep(i,1,n+1){rep(j,1,m+1){
c=cin.get();int res=c;if(c=='.')res='0'+0;if(c=='#')res='0'+10;
mp[i][j]=res-'0';
assert(mp[i][j]<11);
if(mp[i][j]!=0 and mp[i][j]!=10)st[mp[i][j]].push({i,j,s[mp[i][j]]});
if(mp[i][j]==10)vis[i][j]=1;
}cin.get();}
rep(i,0,n+1)mp[i][0]=10; rep(i,0,m+1)mp[0][i]=10;
rep(i,0,n+1)mp[i][m+1]=10; rep(i,0,m+1)mp[n+1][i]=10;
while(1){
bool OUT=1;rep(i,1,p+1){assert(i<11);if(!st[i].empty())OUT=0;}
if(OUT)break;
rep(id,1,p+1){
assert(id<11);
while(!st[id].empty())q.push(st[id].front()),st[id].pop();
while(!q.empty()){
ele now=q.front(); q.pop();
if(vis[now.x][now.y])continue;
int x=now.x,y=now.y,mv=now.move;
mp[x][y]=id; if(mv>0)vis[x][y]=1;
if(mv==0)st[id].push({x,y,s[id]});
if(mv>0 and !mp[x-1][y])q.push({x-1,y,mv-1});
if(mv>0 and !mp[x+1][y])q.push({x+1,y,mv-1});
if(mv>0 and !mp[x][y-1])q.push({x,y-1,mv-1});
if(mv>0 and !mp[x][y+1])q.push({x,y+1,mv-1});
}
}
}
rep(i,1,n+1)rep(j,1,m+1)ans[mp[i][j]]++;
rep(i,1,p+1)cout<<ans[i]<<' '; cout<<'\n';
return 0;
}
標頭、模板請點Submission看
Submission
D. Kilani and the Game 解析(裸BFS、實作)的更多相关文章
- USACO 3.2 msquare 裸BFS
又是个裸BFS... 和西安网赛那道1006一样的,只不过加上了要记录方案.顺便复习map 记录方案直接在bfs队列的结点里加一个vector<int> opt,把从开头一直到当前结点的操 ...
- Kilani and the Game CodeForces - 1105D (bfs)
沙茶bfs打了2小时... queue入队量太大了, 放函数里直接T了, 改成全局46ms #include <iostream> #include <algorithm> # ...
- 裸BFS题若干
1poj 3278 http://poj.org/problem?id=3278 #include<math.h> #include<algorithm> #include&l ...
- Codeforces 1105D(Kilani and the Game,双队列bfs)
AC代码: #include<bits/stdc++.h> #define ll long long #define endl '\n' #define mem(a,b) memset(a ...
- CodeForces - 1105D Kilani and the Game(多源BFS+暴力)
题目: 给出一张游戏地图和每个玩家的位置,每次能移动的步数.p个玩家轮流移动占领地图中的格子(当格子已经被占领时就不能在占领了)在每个玩家都不能移动时游戏结束. 问在游戏结束后,每个玩家占领的格子的数 ...
- poj1724ROADS(BFS)
链接 本来想写spfa 加点什么限制什么的可能就过了 写着写着就成裸BFS了 也没优化就水过了 #include <iostream> #include<cstdio> #in ...
- URAL 1008 - Image Encoding(bfs坑爹题)
坑爹题,两种输入输出互相交换,裸bfs #include <stdio.h> #include <string.h> typedef struct { int x; int y ...
- UVA 10047-The Monocycle(队列bfs+保存4种状态)
题意:给你一张地图,S代表起点,T代表终点,有一个轮盘,轮盘平均分成5份,每往前走一格恰好转1/5,轮盘只能往前进,但可以向左右转90°,每走一步或是向左向右转90° 要花费1单位的时间,问最少的时间 ...
- hdu_1253_胜利大逃亡(bfs+剪枝)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1253 题意:三维BFS,不解释 题解:DFS+剪枝会超时,裸BFS会超时,BFS+剪枝才能AC,有点伤 ...
随机推荐
- http(Hyper Text Transfer Protocol)
一.定义 http(Hyper Text Transfer Protocol):超文本传输协议二.作用 数据传输三.概念 HTTP消息: 1.客户端发向服务器的请求消息 ...
- 【Processing日常2】群星1
之前在CSDN上发表过: https://blog.csdn.net/fddxsyf123/article/details/79747064
- Python2.7集成scrapy爬虫错误解决
运行报错: NotSupported: Unsupported URL scheme 'https':.... 解决方法:降低对应package的版本 主要是scrapy和pyOpenSSL的版本 具 ...
- Spring源码系列——容器的启动过程(一)
一. 前言 Spring家族特别庞大,对于开发人员而言,要想全面征服Spring家族,得花费不少的力气.俗话说,打蛇打七寸,那么Spring家族的"七寸"是什么呢?我心目中的答案一 ...
- Python-迭代协议-__iter__ __next__ iter next yield
iter 本质是for循环调用的实质,for循环通过调用这个函数返回可迭代对象生成器形式,开始迭代取值捕获StopIteration错误退出循环 for循环首先找__iter__方法,然后再找 __g ...
- Python-local variable 'raw_password' referenced before assignment
where? 执行Python程序的时候,报这个错 why? 变量作用域问题,在分支中定义的变量,当满足条件的时候则可以正确得到变量,当不满足条件的时候则报这个错 way? 把变量从分支中抽离到分支上 ...
- [vue-webpack-template] webpack配置全局less引入
1. 项目模板webpack vue init webpack <项目名> 2. 安装依赖 除了less所需的less less-loader两个包以外,还需要安装style-resour ...
- C++系列教程
C++系列教程: 本人是一个高二狗C++小白,之前徘徊在Python和易语言等一些语言之间,这是我几天学习收获的结果,该教程是我自己搜集整理,再加上自己对C++的理解编写的,也是一个偏经验类型的,希望 ...
- 利用mindmaster思维导图学好Python
- LRC 滚动器 + Vue.js
LRC 滚动展示VueJS cnblogs @ Orcim 最 近一直在学习尤大大的这个前端框架.Vue 无疑是一款极易上手的前端框架,因为官方的文档就是中文的,十分"本土化", ...