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. 面经手册 · 第12篇《面试官,ThreadLocal 你要这么问,我就挂了!》

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 说到底,你真的会造火箭吗? 常说面试造火箭,入职拧螺丝.但你真的有造火箭的本事吗,大 ...

  2. 测试工具-XPath使用

    XML有两种MIME类型,即application/xml和text/xml,在HTTP中,MIME Type类型被定义在Content-Type header中.我们经常也会看到接口返回数据类型为X ...

  3. Android Handler 分析学习

    一.Handler简介 Handler 是 Android 中用于线程间交互的机制.与其相关的概念有 Thread.Looper.Runnable.Message.MessageQueue 等. Go ...

  4. JUC并发编程--AQS

    转自: https://www.jianshu.com/p/d8eeb31bee5c 前言 在java.util.concurrent.locks包中有很多Lock的实现类,常用的有Reentrant ...

  5. Markdown 1.0.1

    简介 Markdown 是由 John Gruber 于2004年开发一种轻量级标记语言,它是一个面向web作者的 text-to-HTML 转换工具.Markdown编辑器允许您使用纯文本格式编写, ...

  6. 用ThreadLocal来优化下代码吧

    最近接手了一个老项目,看到一个很有意思的现象. 这个项目中大量的方法入参都会带上user信息,比如这样 它的意图是希望在方法内使用user的信息,但是如此大范围的传递用户信息,第一感觉就是不优雅.那有 ...

  7. PCIE_DMA实例五:基于XILINX XDMA的PCIE高速采集卡

    PCIE_DMA实例五:基于XILINX XDMA的PCIE高速采集卡 一:前言 这一年关于PCIE高速采集卡的业务量激增,究其原因,发现百度"xilinx pcie dma",出 ...

  8. Python练习题 017:三支乒乓球队出赛名单

    [Python练习题 017] 两个乒乓球队进行比赛,各出三人.甲队为a,b,c三人,乙队为x,y,z三人.已抽签决定比赛名单.有人向队员打听比赛的名单.a说他不和x比,c说他不和x,z比.请编程序找 ...

  9. SQL实战——04. 查找所有已经分配部门的员工的last_name和first_name以及dept_no (一个逗号引发的血案)

    查找所有已经分配部门的员工的last_name和first_name以及dept_noCREATE TABLE `dept_emp` (`emp_no` int(11) NOT NULL,`dept_ ...

  10. [源码阅读] 阿里SOFA服务注册中心MetaServer(2)

    [源码阅读] 阿里SOFA服务注册中心MetaServer(2) 目录 [源码阅读] 阿里SOFA服务注册中心MetaServer(2) 0x00 摘要 0x01 MetaServer 注册 1.1 ...