[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
",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
");
return 0;
}
}
printf("%d
",cntMice);
}