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裡),我們要同時防止其他玩家走到這一點,又要讓擁有這個格子的玩家在自己的回合時不會判斷這個格子不能走,我們有兩種實作方式:

  1. 在push入新格子進queue之前先把格子標示為\(visited\),BFS從新格子開始時就不要檢查是否走過了(也就是只在往外走時檢查是否走過)。 這種方法可以某種程度上縮減queue中多餘的元素數量,是比較好的方法。
  2. 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、實作)的更多相关文章

  1. USACO 3.2 msquare 裸BFS

    又是个裸BFS... 和西安网赛那道1006一样的,只不过加上了要记录方案.顺便复习map 记录方案直接在bfs队列的结点里加一个vector<int> opt,把从开头一直到当前结点的操 ...

  2. Kilani and the Game CodeForces - 1105D (bfs)

    沙茶bfs打了2小时... queue入队量太大了, 放函数里直接T了, 改成全局46ms #include <iostream> #include <algorithm> # ...

  3. 裸BFS题若干

    1poj 3278 http://poj.org/problem?id=3278 #include<math.h> #include<algorithm> #include&l ...

  4. 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 ...

  5. CodeForces - 1105D Kilani and the Game(多源BFS+暴力)

    题目: 给出一张游戏地图和每个玩家的位置,每次能移动的步数.p个玩家轮流移动占领地图中的格子(当格子已经被占领时就不能在占领了)在每个玩家都不能移动时游戏结束. 问在游戏结束后,每个玩家占领的格子的数 ...

  6. poj1724ROADS(BFS)

    链接 本来想写spfa 加点什么限制什么的可能就过了 写着写着就成裸BFS了 也没优化就水过了 #include <iostream> #include<cstdio> #in ...

  7. URAL 1008 - Image Encoding(bfs坑爹题)

    坑爹题,两种输入输出互相交换,裸bfs #include <stdio.h> #include <string.h> typedef struct { int x; int y ...

  8. UVA 10047-The Monocycle(队列bfs+保存4种状态)

    题意:给你一张地图,S代表起点,T代表终点,有一个轮盘,轮盘平均分成5份,每往前走一格恰好转1/5,轮盘只能往前进,但可以向左右转90°,每走一步或是向左向右转90° 要花费1单位的时间,问最少的时间 ...

  9. hdu_1253_胜利大逃亡(bfs+剪枝)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1253 题意:三维BFS,不解释 题解:DFS+剪枝会超时,裸BFS会超时,BFS+剪枝才能AC,有点伤 ...

随机推荐

  1. windows提权之mimikatz

    mimikatz privilege::debug #提权命令 sekurlsa::logonPasswords #抓取密码 winmine::infos #扫雷作弊 lsadump::lsa /pa ...

  2. python-igraph

    linux安装python-igraph: $ sudo apt-get install -y libigraph0-dev $ pip install python-igraph ------for ...

  3. Linux 文件系统之入门必看!

    在 Linux 中,最直观.最可见的部分就是 文件系统(file system).下面我们就来一起探讨一下关于 Linux 中国的文件系统,系统调用以及文件系统实现背后的原理和思想.这些思想中有一些来 ...

  4. websocket+sockjs+stompjs详解及实例

    最近有项目需求要用到websocket,刚开始以为很简单,但是随着遇到问题,深入了解,才知道websocket并不是想象中的那么简单,这篇文章主要是考虑websocket在客户端的使用. 1.http ...

  5. Python_快速安装第三方库-pip

    如何快速安装第三方库? 通过python 豆瓣园源https://pypi.douban.com/simple/进行安装,利用国内网速 如何安装? pip -i install https://pyp ...

  6. Arduino control Eeprom by IIC method of using device address in Arduino

    参考: 1.https://www.arduino.cc/ 2.https://www.arduino.cc/reference/en/ 3.https://www.arduino.cc/en/Ref ...

  7. P2034 选择数字 / P2627 [USACO11OPEN]Mowing the Lawn G

    Link 题目描述 给定一行 \(n\) 个非负整数 \(a[1]..a[n]\) .现在你可以选择其中若干个数,但不能有超过 \(k\) 个连续的数字被选择.你的任务是使得选出的数字的和最大. 输入 ...

  8. P4231 三步必杀

    题目描述 问题摘要: N个柱子排成一排,一开始每个柱子损伤度为0. 接下来勇仪会进行M次攻击,每次攻击可以用4个参数l,r,s,e来描述: 表示这次攻击作用范围为第l个到第r个之间所有的柱子(包含l, ...

  9. 「剑指offer」27道Mybatis面试题含解析

    1.什么是Mybatis? Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动.创建连接.创建statement等繁杂 ...

  10. Git操作常用的命令都在这里了。

    创建仓库 git init 在当前目录执行,会生成 .git目录文件,这个和SVN一致. 提交到仓库 git commit -m "first commit" -m:表示提交描述, ...