zoukankan      html  css  js  c++  java
  • [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
    ",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);
    }
    
  • 相关阅读:
    VS2010安装SP1后无法安装VS2010 SDK
    c#异常机制
    精简2003,安装后控制面板无效,点击控制面板就闪一下,返回桌面
    转载 Microsoft .NET Pet Shop 4 架构与技术分析
    JavaScript实用的一些技巧
    asp.net开发常用技巧收集
    Ajax+PHP+jQuery图片截图上传
    如何利用WINPE制作恢复光盘/恢复分区
    C/C++跨平台计时,精确到毫秒级别
    SetLocalInfo修改系统时间,立即生效
  • 原文地址:https://www.cnblogs.com/birchtree/p/14068395.html
Copyright © 2011-2022 走看看