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,有点伤 ...
随机推荐
- Java Set 常用集合 HashSet、LinkedHashSet、TreeSet
Java 中的 Set 是非常常用的数据类型.Set 是无序的 Collection,Java Set 有三个常用的实现类,分别是:HashSet.LinkedHashSet.TreeSet 本文基于 ...
- @lookup注解的使用
背景,如果有一个类C,需要用到类B,如果使用@Autowired注解注入B,那么B每次调用都是同一个对象,即使B不是单例的,现在我希望每次调用B都是不一样的,那么实现方案有2个: 方案A : 每次从容 ...
- Java学习day05
Java学习day05 [switch]属于选择结构,分支语句 语法结构: /* switch(int或string类型字面值或变量) { case int或string类型字面值或变量 : java ...
- 基础篇:深入解析JAVA注解机制
目录 java实现注解的底层原理和概念 五种元注解详解 使用动态代理机制处理注解 spring.AOP和注解机制 (题外)@FunctionalInterface原理介绍 欢迎指正文中错误 关注公众号 ...
- 068 01 Android 零基础入门 01 Java基础语法 08 Java方法 06 参数传递问题——基本数据类型传值
068 01 Android 零基础入门 01 Java基础语法 08 Java方法 06 参数传递问题--基本数据类型传值 本文知识点:参数传递问题--基本数据类型传值 说明:因为时间紧张,本人写博 ...
- Java知识系统回顾整理01基础01第一个程序04创建Eclipse项目
一.为Eclipse设置桌面快捷方式图标 二.双击桌面快捷方式打开Eclipse 三.选择工作区 使用在命令行Hello World中的项目目录e:\project 除了第一次启动eclipse的时候 ...
- 在Jenkins容器中安装docker-compose
首先使用Docker容器安装Jenkins 链接参考 安装成功后使用管理员权限进入到Jenkins容器 docker exec -it -u root jenkins bash 下载docker-co ...
- MeteoInfoLab脚本示例:MODIS AOD
MODIS的气溶胶光学厚度(AOD)产品应用很广,数据可以在Giovanni上下载:http://disc.sci.gsfc.nasa.gov/giovanni/overview/index.html ...
- Java中字符串相关操作(判断,增删,转换)
1:判断字符串中是否包含某个字符(字符串): startsWith(): 这个方法有两个变体并测试如果一个字符串开头的指定索引指定的前缀或在默认情况下从字符串开始位置 此方法定义的语法如下: publ ...
- Termux基础教程(一):技能部署
Termux基础教程 by CUCI Termux 是一个 Android 下一个高级的终端模拟器,开源且不需要 root,支持 apt 管理软件包,十分方便安装软件包,完美支持 Python. PH ...