• Codeforces 1105D Kilani and the Game【BFS】


    <题目链接>

    题目大意:

    每个玩家控制一个颜色去扩张,每个颜色的扩张有自己的速度,一个颜色跑完再跑下一种颜色。在所有颜色不能在继续扩张的时候停止游戏。询问此时各种颜色的数量。

    解题分析:

    就是用BFS去模拟颜色的扩张,但是需要注意的是,本题需要加一些小的优化,比如,每次只用扩张上一轮BFS新更新的点就行。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N int(1e3+7)
     5 #define rep(i,s,t) for(int i=s;i<=t;i++)
     6 int n,m,p;
     7 int sp[15],prenum[15];
     8 char mpa[N][N];bool vis[N][N],go[15];
     9 typedef pair<int,int>paii;
    10 vector<paii>vec[15];
    11 bool fp,flag;
    12 const int dir[][2]={1,0,0,1,-1,0,0,-1};
    13 
    14 struct Node{
    15     int x,y,s;
    16     Node(int _x=0,int _y=0,int _s=0):x(_x),y(_y),s(_s){}
    17 };
    18 
    19 void bfs(int u){
    20     queue<Node>q;
    21     for(int i=vec[u].size()-prenum[u];i<vec[u].size();i++){    //将该人上一轮新扩展的点全部push入列,只对这些点展开搜索,节约时间
    22         int fi=vec[u][i].first,se=vec[u][i].second;
    23         vis[fi][se]=true;
    24         q.push(Node(fi,se,0));
    25     }
    26     int num=0;
    27     while(!q.empty()){
    28         Node now=q.front();q.pop();
    29         int xx=now.x,yy=now.y;
    30         if(now.s==sp[u]){ prenum[u]=num;return; }   //如果步数已经走尽
    31         for(int k=0;k<4;k++){
    32             int nx=xx+dir[k][0];
    33             int ny=yy+dir[k][1];
    34             if(nx<1||nx>n||ny<1||ny>m||vis[nx][ny])continue;
    35             else if(mpa[nx][ny]=='.'){      //只有碰到了'.'才能走
    36                 mpa[nx][ny]= u +'0';
    37                 vec[u].push_back(paii(nx,ny));     //标记这一步已经被占领
    38                 vis[nx][ny]=true;  
    39                 flag=true;     //有新扩展的点
    40                 num++;         //记录当前一轮push进去多少个点
    41                 q.push(Node(nx,ny,now.s+1));    //将这一步push入队列
    42             }
    43         }
    44     }
    45     prenum[u]=num;
    46 }
    47 
    48 int main(){
    49     scanf("%d%d%d",&n,&m,&p);
    50     rep(i,1,p)scanf("%d",&sp[i]);
    51     rep(i,1,n){ 
    52         scanf("%s",mpa[i]+1);
    53         rep(j,1,m){
    54             if(mpa[i][j]>='1'&&mpa[i][j]<=p+'0'){        //如果碰到数字
    55                 vec[mpa[i][j]-'0'].push_back(paii(i,j));      //将该点坐标记录下
    56             }
    57         }
    58     }
    59     rep(i,1,p)prenum[i]=vec[i].size();    //得到一开始各个起点的个数
    60     memset(vis,false,sizeof(vis));
    61     memset(go,true,sizeof(go));
    62     while(true){        //如果有点能够一直扩展,就继续
    63         fp=false;
    64         for(int i=1;i<=p;i++){
    65             if(!go[i])continue;
    66             if(go[i])flag=false,bfs(i);
    67             if(!flag)go[i]=false;      //如果这个人本轮没有走过,那么标记,下次再轮到他的时候直接跳过 
    68             if(flag)fp=true;     //判断是否有人能够走 
    69         }
    70         if(!fp)break;
    71     }
    72     rep(i,1,p){
    73         i==p?printf("%d
    ",vec[i].size()):printf("%d ",vec[i].size());
    74     }
    75 }

    2019-02-17

  • 相关阅读:
    c#调用dll,::CoInitialize(NULL)出错
    使用 Anthem.NET 的常见回调(Callback)处理方式小结
    主题和皮肤学习
    得到任意网页源代码 (利用WebClient和WebRequest类)
    HTML marquee标签详解
    制作一个简单的天气预报
    CSS中的类class和标识id选择符(.和#号)
    String split '.'
    Map 的 clear() 方法会清空 Map对象
    sqLite 执行查询语句时报错__及SimpleCursorAdapter
  • 原文地址:https://www.cnblogs.com/00isok/p/10392291.html
Copyright © 2020-2023  润新知