[CTSC2002]灭鼠行动(模拟)

[CTSC2002]灭鼠行动(模拟)

题面

分析

对于模拟题来说,代码本身就是最好的题解。感觉写的可读性还行吧

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define MAXN 1000
#define MAXCNT 10000
//消灭magic number 
//方向常量 
#define NORTH 0
#define EAST 1
#define SOUTH 2
#define WEST 3 //这样定义可以使得左右转方便
#define DIRSZ 4
//性别 
#define MALE 0
#define FEMALE 1 
#define SLEEPTIME 3//昏睡时间 
#define BREEDTIME 2//繁殖时等待的时间 
#define BREEDAGE 5//最小繁殖年龄 
using namespace std;
int curTime;
int maxCntMice;
bool isCon[MAXN+5][MAXN+5][DIRSZ];//每个点往四个方向是否有边
const int dirx[DIRSZ]={-1,0,1,0},diry[DIRSZ]={0,1,0,-1};
inline int goLeft(int dir){
    return (dir-1+DIRSZ)%DIRSZ;
}
inline int goRight(int dir){
    return (dir+1)%DIRSZ;
}

struct mouse{
	int x;
	int y;
	int dir;
	int turnCnt;
	int gender;
	int age;
	int wakeTime;//距离开始活动的时间差 
	int breedTime;//生出下一代的时间 
	bool isPreg;  
	mouse(){}
	mouse(int _x,int _y,int _dir,int _gender,int _age){
		x=_x,y=_y,dir=_dir,gender=_gender;
        turnCnt=0;
        age=_age;
        wakeTime=0;
        breedTime=0;
        isPreg=0;
	}
	void Move(){
		mouse cur=*this;
		cur.age++;
		cur.breedTime=0; 
        if(isCon[cur.x][cur.y][cur.dir]){//可以直接走
            cur.x+=dirx[cur.dir];
            cur.y+=diry[cur.dir];
        }else{
            if(isCon[cur.x][cur.y][goLeft(cur.dir)]&&isCon[cur.x][cur.y][goRight(cur.dir)]){
                cur.turnCnt++;//两个岔道
                if(cur.turnCnt%2==1) cur.dir=goLeft(cur.dir);
                else cur.dir=goRight(cur.dir);
            }else if(isCon[cur.x][cur.y][goLeft(cur.dir)]){
                cur.dir=goLeft(cur.dir);
            }else if(isCon[cur.x][cur.y][goRight(cur.dir)]){
                cur.dir=goRight(cur.dir);
            }else{//死路
                cur.dir=goRight(cur.dir);//连续右转
            }
        }
        *this=cur;
	} 
    void kill(){age=-1;}
    void switchGender(){gender^=1;}
    bool isDead(){return age==-1;}
    void sleep(){
        wakeTime+=3;
        if(breedTime>curTime) breedTime+=3; 
 	}
 	void debug(){
 		printf("(%d,%d) dir=%d\n",x,y,dir);
	}
}; 
int cntMice;
mouse mice[MAXCNT+5];

#define STRONG 1
#define RADIATION 2
#define TIMING 3
#define BIOLOGY 4
int bombLength;
int bombRadius;
inline int dist(int x1,int y1,int x2,int y2){
    return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
struct bomb{
    int type;
	int x;
	int y;
	int tim;
    bomb(){}
    bomb(int _type,int _x,int _y,int _tim){
        type=_type,x=_x,y=_y,tim=_tim;
    }
	friend bool operator < (bomb p,bomb q){
        return p.tim<q.tim;
    }
}; 
int bombCnt;
bomb bombs[MAXN+5];
void explode(bomb b){
    static bool isRange[MAXN+5][MAXN+5];//记录能被炸的区域
    if(b.type==STRONG){
        memset(isRange,0,sizeof(isRange));
        for(int i=0;i<DIRSZ;i++){
            int tx=b.x,ty=b.y;
            isRange[tx][ty]=1;
            for(int j=1;j<=bombLength;j++){
                if(!isCon[tx][ty][i]) break;
                tx+=dirx[i];
                ty+=diry[i];
                isRange[tx][ty]=1;
            }
        }
        for(int i=1;i<=cntMice;i++) if(isRange[mice[i].x][mice[i].y]) mice[i].kill();
        
    }else if(b.type==RADIATION){
        for(int i=1;i<=cntMice;i++){
            if(dist(b.x,b.y,mice[i].x,mice[i].y)<=bombRadius*bombRadius) mice[i].sleep();
            
        }
    }else if(b.type==TIMING){
        for(int i=1;i<=cntMice;i++){
            if(b.x==mice[i].x&&b.y==mice[i].y) mice[i].kill();
        }
        
    }else if(b.type==BIOLOGY){
        for(int i=1;i<=cntMice;i++){
            if(b.x==mice[i].x&&b.y==mice[i].y) mice[i].switchGender();
        }
    }
}
void clearDead(){//清除死老鼠
    static mouse tmp[MAXCNT+5];
    int ptr=0;
    for(int i=1;i<=cntMice;i++) if(!mice[i].isDead()) tmp[++ptr]=mice[i];
    cntMice=ptr;
//    cerr<<"Time="<<curTime<<endl;
    for(int i=1;i<=cntMice;i++){
    	mice[i]=tmp[i];
//    	mice[i].debug();
	}
}
void bombMice(){
    static int ptr=1;
    while(ptr<=bombCnt&&bombs[ptr].tim<=curTime){
        explode(bombs[ptr]);
        ptr++;
    }
}
void moveMice(){
    for(int i=1;i<=cntMice;i++){
        if(mice[i].wakeTime==0) mice[i].Move();
        else mice[i].wakeTime--; 
    }
}
void breedMice(){
    static int cnt[MAXN+5][MAXN+5];
   	memset(cnt,0,sizeof(cnt)); 
    for(int i=1;i<=cntMice;i++) cnt[mice[i].x][mice[i].y]++;
    for(int i=1;i<=cntMice;i++){
        for(int j=i+1;j<=cntMice;j++){
            if(mice[i].x==mice[j].x&&mice[i].y==mice[j].y&&
               cnt[mice[i].x][mice[i].y]==2/*恰好两只老鼠*/&&
               mice[i].gender!=mice[j].gender&&
               mice[i].age>=BREEDAGE&&mice[j].age>=BREEDAGE&&
               mice[i].wakeTime==0&&mice[j].wakeTime==0&&
               mice[i].breedTime==0&&mice[j].breedTime==0
               &&!mice[i].isPreg&&!mice[j].isPreg
            ){
                mice[i].breedTime=mice[j].breedTime=curTime+BREEDTIME;//t+2秒后生 
                mice[i].wakeTime=mice[j].wakeTime+=BREEDTIME+1;//t+3秒后活动 
                if(mice[i].gender==FEMALE) mice[i].isPreg=1;
                else mice[j].isPreg=1;
            }
        }
    }
    for(int i=1;i<=cntMice;i++){
        //小老鼠会延迟2时间出生,所以处理现在该出生的老鼠
        if(mice[i].breedTime==curTime&&mice[i].isPreg){
            for(int j=0;j<DIRSZ;j++){
                if(isCon[mice[i].x][mice[i].y][j]) mice[++cntMice]=mouse(mice[i].x,mice[i].y,j,j%2,0);
            }
            mice[i].isPreg=0;
        }
    }
}
int n,m;
int main(){
    char cmd[10];
    scanf("%d %d %d %d",&bombLength,&bombRadius,&n,&m);
    for(int i=1,x;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&x);
            for(int k=0;k<DIRSZ;k++) if(x&(1<<k)) isCon[i][j][k]=1;   
        }
    }
    scanf("%d",&cntMice);
    for(int i=1;i<=cntMice;i++){
        scanf("%d %d %s",&mice[i].x,&mice[i].y,cmd);
        if(cmd[0]=='N') mice[i].dir=NORTH;
        if(cmd[0]=='E') mice[i].dir=EAST;
        if(cmd[0]=='S') mice[i].dir=SOUTH;
        if(cmd[0]=='W') mice[i].dir=WEST;
        scanf("%s",cmd);
        if(cmd[0]=='X') mice[i].gender=MALE;
        else mice[i].gender=FEMALE;
        mice[i].age=BREEDAGE;//初始时成年 
    }
    scanf("%d",&bombCnt);
    scanf("%d",&maxCntMice);
    for(int i=1;i<=bombCnt;i++){
        scanf("%d %d %d %d",&bombs[i].type,&bombs[i].tim,&bombs[i].x,&bombs[i].y);
        if(bombs[i].type==3) bombs[i].tim+=3;
    }
    sort(bombs+1,bombs+1+bombCnt);
    int maxTime;
    scanf("%d",&maxTime);
    for(curTime=0;curTime<=maxTime;curTime++){
    	clearDead();
        bombMice();
        clearDead();
        breedMice();
        clearDead();
        moveMice();
        if(cntMice>maxCntMice){
            printf("-1\n");
            return 0;
        }
    }
    printf("%d\n",cntMice);
}
posted @ 2020-12-01 15:30  birchtree  阅读(150)  评论(0编辑  收藏  举报