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. solr综合案例

    1.  综合案例 1.1. 需求 使用Solr实现电商网站中商品信息搜索功能,可以根据关键字.分类.价格搜索商品信息,也可以根据价格进行排序,并且实现分页功能. 界面如下: 1.2分析 开发人员需要的 ...

  2. Codeforces1146G. Zoning Restrictions

    Description You are planning to build housing on a street. There are n spots available on the street ...

  3. 刷题[WUSTCTF2020]CV Maker

    解题思路 好家伙,打开一看像是cms,又看名字CV Maker.我以为直接要搜cve打了.搜了一会发现没什么啊.那先正常做把. 注册 注册成功后这里报错,猜测可能有注入点.先放在这里,继续登陆.发现是 ...

  4. 交互平台 - Processing - 开发模板(仿Openframeworks)

    之前在CSDN上发表过: https://blog.csdn.net/fddxsyf123/article/details/62425251

  5. System Verilog随笔(1)

    测试文件该怎么写? 首先看一个简单代码案例: `timescale 1ns/10ps //1 module test;   //2 intput wire[15:0] a; output reg[15 ...

  6. git push 提交时出错 the remote end hung up unexpectedly

    错误原因 与远程服务的连接中断,但是检查发现origin还在,可能是文件太大,缓存不够,增加缓存大小 解决方案 专案目录 >.git >config 在末尾增加如下代码 [http] po ...

  7. Python练习题 031:Project Euler 003:最大质因数

    本题来自 Project Euler 第3题:https://projecteuler.net/problem=3 # Project Euler: Problem 3: Largest prime ...

  8. 064 01 Android 零基础入门 01 Java基础语法 08 Java方法 02 无参带返回值方法

    064 01 Android 零基础入门 01 Java基础语法 08 Java方法 02 无参带返回值方法 本文知识点:无参带返回值方法 说明:因为时间紧张,本人写博客过程中只是对知识点的关键步骤进 ...

  9. ATMEGA的SPI总线 - 第2部分

    参考: 1.https://www.yiboard.com/thread-783-1-1.html 2.https://mansfield-devine.com/speculatrix/2018/01 ...

  10. error C2065: “uint8_t”: 未声明的标识符

    转载:https://blog.csdn.net/lys07962000/article/details/12052571 参考: http://blog.csdn.net/chenxin_130/a ...