SXJM--CSUSTOJ-1029(简单模拟+预处理)

题目链接https://csustacm.fun/problem/1029

Description

现在你参加了SXJM竞赛,你的一名队友需要你模拟一种细胞的增殖过程的影响。

假设这种细胞均为1*1的二维平面生物,他们生活在一个无限大的二维平面中该种细胞增值过程如下:

  1. 如果一个没有活细胞的空格周围8个空格中恰好有两个活细胞,则这个空格在下一代会出现一个活细胞
  2. 如果一个活细胞的周围8个空格中的活细胞数量为0或者大于等于4,则这个活细胞在下一代会死亡(既消失)
  3. 如果一个活细胞周围8空格的活细胞数量在1-3之间,则这个活细胞存活到下一代。

你的队友会给出一个初始的状态n*m个格子的图。在SXJM比赛中,你需要写出一个可视化程序,来模拟这个过程。 但是现在,你只需要告诉你的队友 在经过X代繁衍后,会有多少个活着的细胞。

Input

第一行输入3个整数n,m,t(1<=n,m<=5,1<=t<=400)

之后n行,每行为一个长度为m的01字符串,1代表这个格子有一个活着的细胞

接下来有t行,表示有t次询问,每行包含一个数字Xi,询问经过Xi(Xi<=400)代繁衍后,有多少个活着的细胞

Output

输出包含t行 每行输出一个数字表示Xi代后,有多少个活着的细胞

Sample Input 1 

3 3 3
000
110
010
0
1
2

Sample Output 1

3
7
10

就是个大模拟,关键是它的平面是无限大的,它可以一直繁殖,但Xi只有400,也就是说这个矩阵最多扩充400次,那么他的大小极限也就是800*800而已,每一次向左,右,上,下扩充一次,那么我们可以将它先放在二维数组的中间以便扩充,为了减小常数,我们不能每次都从1到800跑一遍,我们从设置一个边界,每次边界向外扩充就好了,这个边界可以直接用xl,xr,yl,yr(最上面,下面,左边,右边)控制

以下是AC代码:

#include <bits/stdc++.h>
using namespace std;

char s[10][10];
int ans[500],a[810][810][2];
int dx[]={-1,-1,-1,0,0,1,1,1},dy[]={-1,0,1,-1,1,-1,0,1};

int ok1(int x,int y,int id)
{
    int sum=0;
    for (int i=0; i<8; i++){
        int xx=x+dx[i],yy=y+dy[i];
        if (a[xx][yy][id]) sum++;
    }
    if (sum==2) return 1;
    return 0;
}

int ok2(int x,int y,int id)
{
    int sum=0;
    for (int i=0; i<8; i++){
        int xx=x+dx[i],yy=y+dy[i];
        if (a[xx][yy][id]) sum++;
    }
    if (sum==0 || sum>=4) return 1;
    return 0;
}

int main()
{
    int n,m,t;
    scanf ("%d%d%d",&n,&m,&t);
    for (int i=1; i<=n; i++)
        scanf ("%s",s[i]+1);
    for (int i=1; i<=n; i++)
        for (int j=1; j<=m; j++)
            a[401+i][401+j][0]=s[i][j]-'0';
    int mk=0,xl=402,xr=401+n,yl=402,yr=401+m;
    for (int o=0; o<=400; o++){
        for (int i=xl; i<=xr; i++)
            for (int j=yl; j<=yr; j++){
                if (a[i][j][mk]==1) ans[o]++;
            }
        for (int i=xl-1; i<=xr+1; i++)
            for (int j=yl-1; j<=yr+1; j++){
                if (a[i][j][mk]){
                    if (ok2(i,j,mk)) a[i][j][mk^1]=0;
                    else a[i][j][mk^1]=1;
                }
                else {
                    if (ok1(i,j,mk)) a[i][j][mk^1]=1;
                    else a[i][j][mk^1]=0;
                }
            }
        xl--,xr++,yl--,yr++;
        mk^=1;
    }
    for (int i=1; i<=t; i++){
        int x;
        scanf ("%d",&x);
        printf ("%d\n",ans[x]);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值