P7196 灭鼠行动 题解

· · 题解

这道题就是一道大模拟,跟那个与猪打牌的题差不多,但是简单一点。

主要注意以下细节:

还有一些隐含的条件,经过不断尝试以及网络搜寻(这里参考了这篇博客):

还有一个根据题目可推得但是有些奇怪的结论:

以上就是我总结出来比较重要的一些细节。对于时间的运转,我采取的是仿同上文链接给出的,每一秒计算本一秒操作以及下一秒的状态。

UPD:这里附上一个我自己写的生成数据的代码。

具体代码实现见下。

#include<bits/stdc++.h>
#define rint register int
#define fu(i,a,b,d,c) for(rint i=a;i<=(b)&&c;i+=d)
#define fd(i,a,b,d,c) for(rint i=a;i>=(b)&&c;i-=d)
using namespace std;
inline int read(){
    char c=0,f=1;int num=0;
    while(c<'0'||c>'9'&&c!='-')((c=getchar())=='-')&&(f=-f);
    while(c>='0'&&c<='9')num=(num<<1)+(num<<3)+(c^48),c=getchar();
    return num*f;
}
#define N 1
#define E 2
#define S 4
#define W 8
#define XY 1
#define XX 2
#define BOMB 1
#define RAY 2
#define T_BOMB 3
#define B_BOMB 4
const int dx[9]={0,-1,0,0,1,0,0,0,0},dy[9]={0,0,1,0,0,0,0,0,-1};
int L,R,n,m,K,Limit,P,TimeLimit,curTime,mouseCnt;
int pipes[55][55];
struct Mouse{
    int age,sex,isProducing,towards,facingCross,x,y,stopTime,produceTime;
    Mouse(){
        age=sex=isProducing=towards=facingCross=x=y=stopTime=produceTime=0;
    }
};
struct Weapon{
    int x,y,type,setTime,occurTime;
    bool operator<(const Weapon b)const{
        return occurTime<b.occurTime;
    }
    Weapon(){
        x=y=type=setTime=occurTime=0;
    }
};
vector <Mouse> mice;
vector <Weapon> weapons;
int weaponPointer=0;
void produceNewMouse(int x,int y){
    Mouse tmp;
    tmp.x=x,tmp.y=y,tmp.age=0;
    if((pipes[x][y]&N)){
        tmp.towards=N,tmp.sex=XY;
        mice.push_back(tmp);
    }
    if((pipes[x][y]&E)){
        tmp.towards=E,tmp.sex=XX;
        mice.push_back(tmp);
    }
    if((pipes[x][y]&S)){
        tmp.towards=S,tmp.sex=XY;
        mice.push_back(tmp);
    }
    if((pipes[x][y]&W)){
        tmp.towards=W,tmp.sex=XX;
        mice.push_back(tmp);
    }
}
void moveMouse(Mouse& mouse){
    int x=mouse.x,y=mouse.y,tow=mouse.towards;
    if(pipes[x][y]&tow){
        mouse.x+=dx[tow];
        mouse.y+=dy[tow];
        return;
    }
    //如题描述 
    if(tow==N||tow==S){
        if((pipes[x][y]&E)&&(pipes[x][y]&W)){
            if(!(mouse.facingCross&1)){
                if(tow==N)mouse.towards=W;
                if(tow==S)mouse.towards=E;
            }else{
                if(tow==N)mouse.towards=E;
                if(tow==S)mouse.towards=W;
            }
            mouse.facingCross++;
        }
        else if((pipes[x][y]&W)&&!(pipes[x][y]&E))mouse.towards=W;
        else if((pipes[x][y]&E)&&!(pipes[x][y]&W))mouse.towards=E;
        else mouse.towards=W;
    }
    if(tow==W||tow==E){
        if((pipes[x][y]&S)&&(pipes[x][y]&N)){
            if(!(mouse.facingCross&1)){
                if(tow==W)mouse.towards=S;
                if(tow==E)mouse.towards=N;
            }else{
                if(tow==W)mouse.towards=N;
                if(tow==E)mouse.towards=S;
            }
            mouse.facingCross++;
        }
        else if((pipes[x][y]&N)&&!(pipes[x][y]&S))mouse.towards=N;
        else if((pipes[x][y]&S)&&!(pipes[x][y]&N))mouse.towards=S;
        else mouse.towards=N;
    }
}
void mouseProduce(Mouse& mouse){
    //需满足条件 1.到达年龄 2.不被眩晕 3.未在进行繁殖  
    if(mouse.stopTime||mouse.produceTime||mouse.isProducing||!(mouse.age>=5))return;
    int atMyPos=0;
    for(rint Mouse2=0;Mouse2<mice.size();Mouse2++)if(mice[Mouse2].x==mouse.x&&mice[Mouse2].y==mouse.y)atMyPos++;
    if(atMyPos!=2)return;
    for(rint Mouse2=0;Mouse2<mice.size();Mouse2++)
    if(mice[Mouse2].x==mouse.x&&mice[Mouse2].y==mouse.y&&!mice[Mouse2].stopTime
    &&!mice[Mouse2].isProducing&&mice[Mouse2].sex!=mouse.sex&&mice[Mouse2].age>=5
    &&!mice[Mouse2].produceTime){
        mouse.produceTime=mice[Mouse2].produceTime=curTime+2,mouse.stopTime=mice[Mouse2].stopTime+=3;
        if(mouse.sex==XX)mouse.isProducing=1;
        else mice[Mouse2].isProducing=1;
        break;
    }
}
void dfsForBD(int x,int y,int dir,int lastlength){
    if(lastlength>L)return;
    for(rint nowMouse=0;nowMouse<(int)mice.size();){
        if(mice[nowMouse].x==x&&mice[nowMouse].y==y)mice.erase(mice.begin()+nowMouse);
        else nowMouse++;
    }
    if(pipes[x][y]&dir)dfsForBD(x+dx[dir],y+dy[dir],dir,lastlength+1);
}
void bombOccur(int x,int y){
    if(pipes[x][y]&N)dfsForBD(x,y,N,0);
    if(pipes[x][y]&E)dfsForBD(x,y,E,0);
    if(pipes[x][y]&S)dfsForBD(x,y,S,0);
    if(pipes[x][y]&W)dfsForBD(x,y,W,0);
}
void rayOccur(int x,int y){
    for(rint nowMouse=0;nowMouse<mice.size();nowMouse++)
    if((mice[nowMouse].x-x)*(mice[nowMouse].x-x)+(mice[nowMouse].y-y)*(mice[nowMouse].y-y)<=R*R)
        mice[nowMouse].stopTime+=3,mice[nowMouse].produceTime+=3;
}
void t_bombOccur(int x,int y){
    for(rint nowMouse=0;nowMouse<mice.size();){
        if(mice[nowMouse].x==x&&mice[nowMouse].y==y)mice.erase(mice.begin()+nowMouse);
        else nowMouse++;
    }
}
void b_bombOccur(int x,int y){
    for(rint nowMouse=0;nowMouse<mice.size();nowMouse++)
    if(mice[nowMouse].x==x&&mice[nowMouse].y==y)mice[nowMouse].sex=3-mice[nowMouse].sex;
}
void weaponAct(){
    while(weaponPointer<weapons.size()&&weapons[weaponPointer].occurTime==curTime){
        Weapon tmp=weapons[weaponPointer];
        if(tmp.type==BOMB)bombOccur(tmp.x,tmp.y);
        else if(tmp.type==RAY)rayOccur(tmp.x,tmp.y);
        else if(tmp.type==T_BOMB)t_bombOccur(tmp.x,tmp.y);
        else if(tmp.type==B_BOMB)b_bombOccur(tmp.x,tmp.y);
        weaponPointer++;
    }
}
void checkOver(){
    if(mice.size()>Limit){
        printf("-1");
        exit(0);
    }
}
signed main(){
    L=read(),R=read(),n=read(),m=read();
    fu(i,1,n,1,1)fu(j,1,m,1,1)pipes[i][j]=read();
    K=read();
    fu(i,1,K,1,1){
        int x,y;char t,s;
        scanf("%d %d %c %c\n",&x,&y,&t,&s);
        Mouse tmp;
        tmp.x=x,tmp.y=y;
        if(t=='N')tmp.towards=N;
        if(t=='E')tmp.towards=E;
        if(t=='S')tmp.towards=S;
        if(t=='W')tmp.towards=W;
        tmp.sex=(s=='X'?XY:XX),tmp.age=5;
        mice.push_back(tmp);
    }
    P=read(),Limit=read();
    fu(i,1,P,1,1){
        int ty=read(),t=read(),x=read(),y=read();
        Weapon tmp;
        tmp.x=x,tmp.y=y,tmp.type=ty,tmp.setTime=t;
        if(ty==T_BOMB)tmp.occurTime=t+3;
        else tmp.occurTime=t;
        weapons.push_back(tmp);
    }
    //按发生时间排序 
    sort(weapons.begin(),weapons.end());
    TimeLimit=read();
    checkOver();
    for(curTime = 0; curTime <= TimeLimit;curTime++){
        //武器运作 
        weaponAct();
        //检查繁殖 
        for(rint nowMouse=0;nowMouse<mice.size();nowMouse++)mouseProduce(mice[nowMouse]);
        //检查出生 
        for(rint nowMouse=0;nowMouse<mice.size();nowMouse++){
            if(mice[nowMouse].produceTime==curTime&&mice[nowMouse].isProducing){
                produceNewMouse(mice[nowMouse].x,mice[nowMouse].y);
                mice[nowMouse].isProducing=0;
            }
        }
        checkOver();//事实上这一句在下文for循环之前或之后均无影响,因为下文只有运动,对答案无贡献
        //计算下一秒的状态,位置 
        for(rint nowMouse=0;nowMouse<mice.size();nowMouse++){
            if(mice[nowMouse].stopTime)mice[nowMouse].stopTime--;
            else mice[nowMouse].age++,mice[nowMouse].produceTime=0,moveMouse(mice[nowMouse]);
        }
    }
    printf("%d",mice.size());
}