bzoj2548[Cstc2002]滅鼠行動

Description


最近,有一些繁殖力很強的老鼠在下水道非常猖獗,滅鼠特工隊正在計劃消滅這些老鼠。下水道只有東西方向和南北方向的管道,如圖所示。

滅鼠特工隊的隊員擁有強大的武器。他們將在某些時刻t在某些位置(x,y)放置武器。他們所使用的武器包括:

1.        強力炸彈:它的攻擊範圍限定在管道內部,是沿豎直和水平方向,離(x,y)的距離不超過L的區域,但是不能穿透下水道壁。它將在放置之後立刻爆炸,且攻擊範圍內的老鼠將被全部炸死。

2.        神祕射線:它的攻擊範圍是以(x,y)爲圓心,半徑爲R的圓,而且可以穿透下水道壁。射線在時刻t施放後,將使攻擊範圍內的所有老鼠立刻陷入昏迷狀態,失去知覺,停止一切生理活動,待到第t+3時刻才能恢復(保持失去知覺前的朝向)。如果在昏迷狀態中再次受到射線攻擊,那麼它將再推遲3個時刻恢復。例如,若老鼠在時刻t和時刻t+1個受到一次射線的攻擊,則它要昏迷到第t+3+3時刻才能恢復知覺。恢復知覺以後,老鼠將繼續以前的生理活動。

3.        定時炸彈:它的攻擊範圍僅包括(x,y)。它在時刻t放置後,將在第t+3時刻爆炸,爆炸時處在(x,y)點的老鼠將全部被炸死。

4.        生物炸彈:它的攻擊範圍僅包括(x,y)。它將在放置之後立刻爆炸,使處在(x,y)點的所有老鼠的性別改變(無論大小,雌變成雄,雄變成雌),但不影響老鼠的正常生理活動。

雖然特工隊的實力很強,但是老鼠的實力也不容忽視。

我們定義,相鄰兩個時刻之間是一個時間單位。從t=0時刻開始,每隻老鼠就從初始位置向某一初始方向運動。只要前方有管道,如上圖中沿方向N到達點A,老鼠就會一直向前走,運動速度爲1。否則,如果只有左邊或者只有右邊有管道,如上圖中沿方向E到達點B時,再不能沿原方向繼續前進,它就會花費一個時間單位朝該方向原地轉動90度,即它將改變方向朝向S。如果它左邊和右邊都有管道,如上圖中沿方向W到達點C,老鼠會回憶這是第幾次處於這種情況。如果是第奇數次遇到,它會向左轉,第偶數次就向右轉。如果它處於一條死路的盡頭,如上圖中沿方向W到達點D,那麼它會花費兩個時間單位連續向右轉兩次,即它將改變方向朝向E

    如果在t時刻某點恰好只有兩隻老鼠,一隻爲成年雄老鼠,一隻爲成年雌老鼠,則它們將會因爲進行繁殖而在該點停留兩個單位時間,t+2時刻會在該點對每個有管道的方向生出一隻朝着該方向的小老鼠,南北方向爲雄小老鼠,東西方向爲雌小老鼠。如上圖中的C點,t時刻恰好只有兩隻老鼠,它們都已成年且性別相異,那麼在第t+2時刻就會在該點生出三隻小老鼠,它們分別朝向NSE,性別分別是雄性、雄性、雌性。小老鼠一出生就立刻開始移動,而成年老鼠需要再休息一個時間單位,即在t+3時刻繼續活動(兩隻老鼠都保持生育前的朝向)。小老鼠需要成長5個時間單位纔會長成爲成年老鼠。

    特工隊現在制定了一套滅鼠計劃,其中包括在下水管道放置武器的位置、時間和類型。你需要幫他們計算滅鼠行動的效果,如果在該計劃實施的過程中,老鼠的數量超過了某個限定值,就會爆發鼠疫。

 

Input

第一行爲4個整數L R m n(0<=L,R<=10,1<=m,n<=50),其中L代表強力炸彈的有效攻擊距離,R代表神祕射線的作用半徑,mn代表下水道平面圖的規模。x座標的範圍爲[1,m], y座標的範圍爲[1,n]

    從第2行到第m+1行爲下水道結構圖。我們用方向數1代表N(),用方向數2代表E(),用方向數4代表S(),用方向數8代表W(西)。第i+1行的第j個數字ci,j代表點(i,j)處有管道連接的所有方向數之和,如上圖中的點B的方向數之和爲12

    m+2行爲一個整數K1<=K<=50),代表時刻0時老鼠的個數(此時老鼠都是成年的)。

    m+3行到第m+K+2行每行描述一隻老鼠,包括該老鼠的初始座標(x,y) (1<=x<=m, 1<=y<=n),朝向(’E’,’S’,’W’,’N’)以及性別(’X’=雄,’Y’=雌)。輸入保證每個老鼠都在水管內。

    m+K+3行爲兩個整數PLimit(1<=P, Limit<=100),分別表示特工隊準備使用的武器個數以及控制鼠疫發生的老鼠數量的極限。

    m+K+4行到第m+K+P+3行每行描述一個武器,包括該武器的類型(1-強力炸彈,2-神祕射線,3-定時炸彈,4-生物炸彈),放置的時刻t(t>=1),放置的座標(x,y) (1<=x<=m, 1<=y<=n),輸入保證武器放置在管道內。武器按照放置的時間不降序排列。

    最後一行包含一個整數Time(1<=Time<=1000),表示模擬的結束時刻。Time保證比所有武器的放置時刻大。

 

Output

包含一個整數。如果爆發了鼠疫,該整數爲-1,否則該整數爲時刻Time的老鼠數目。

 

Sample Input

1 1 3 3
6 14 12
7 15 13
3 11 9
3
1 3 W X
1 2 W X
3 3 S X
3 100
1 1 2 2
3 1 3 1
2 2 3 2
10

Sample Output

1

HINT

各個時刻每隻老鼠的情況如下表:


時刻


老鼠1


老鼠2


老鼠3


座標


朝向


狀態


座標


朝向


狀態


座標


朝向


狀態


0


(1,3)


W


正常


(1,2)


W


正常


(3,3)


S


正常


1


N/A


N/A


死亡


(1,1)


W


正常


(3,3)


W


正常


2


N/A


N/A


死亡


(1,1)


S


正常


(3,2)


W


昏迷


3


N/A


N/A


死亡


(2,1)


S


正常


(3,2)


W


昏迷


4


N/A


N/A


死亡


N/A


N/A


死亡


(3,2)


W


昏迷


5


N/A


N/A


死亡


N/A


N/A


死亡


(3,2)


W


正常


Source


1589479

  ksq2013 2548 Accepted 1368 kb 20 ms C++/Edit 5120 B 2016-08-13 19:58:14

我的思路:因爲該題給定了模擬的結束時刻,所以可以

1.枚舉時刻從0到結束時間。

0)若有機關會觸發,轉(1),否則轉(2)

(1)觸發該時刻的滅鼠機關,模擬對老鼠產生的影響;

(2)枚舉該時刻活動的老鼠,進行1);

1)枚舉所有老鼠(昏迷或非昏迷)

(1)若有雌雄鼠且成長值爲0(意爲成年鼠)位於同一座標,則進行繁殖,昏迷時間+3,時刻+2該點的小鼠多出三隻,成長值=5

(2)否則,若老鼠昏迷,昏迷時間--

(3)否則,小老鼠的成長值爲0則視作大老鼠。

(4)否則,小老鼠的成長值--

hzwer的題解:

此題最大的難點在於。。。網絡上下的數據第7個點數據有誤,答案似乎是22

而且要非常機智的先處理炸彈,再處理繁殖,因爲有可能某時刻出生的小老鼠被變性了

其餘沒什麼坑點吧。。注意一下眩暈的老鼠不能開始繁殖,兩隻繁殖完的老鼠如果一次移

動後仍然在一起且這個格子沒有其他老鼠就可以繁殖,而不是兩隻在原地不停繁殖(我的疏漏點)

反思:1.忘記考慮老鼠的行動了;

2.此處切忌,動作不可重疊(不能既繁衍又移動),時間不能重疊(不能同時解除昏迷又移動又成長),武器的優先級最高(一定在老鼠的任何行動之前發動合法的武器);

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
bool vis[111][111];
int mp[111][111],num[55][55];
int L=0,R=0,M=0,n=0,tot=0,P=0,limit=0,T=0,cur_t=0,cur_w=0;
//const int dx[]={0,-1,0,1};//NESW
//const int dy[]={-1,0,1,0};
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int bin[4]={1,2,4,8};
struct mouse{
    int x,y,pos,grow,breed,stu;
    bool sex,dead,turn;
}m[111];
struct weapon{
    int type,t,x,y;
    bool operator<(const weapon h)const{
        return t<h.t;
    }
}b[111];
inline int pw(int x)
{return x*x;}
inline void wp1(weapon k)
{
    memset(vis,0,sizeof(vis));
    for(int i=0;i<4;i++){
        int tx=k.x,ty=k.y,l=0;
        vis[tx][ty]=1;
        while(mp[tx][ty]&bin[i]){//binary operation;
            tx+=dx[i],ty+=dy[i];
            l++;
            if(l>L)break;
            vis[tx][ty]=1;
        }
    }
    for(int i=1;i<=tot;i++)
        if(vis[m[i].x][m[i].y])
            m[i].dead=1;
}
inline void wp2(weapon k)
{
    for(int i=1;i<=tot;i++)
        if(pw(m[i].x-k.x)+pw(m[i].y-k.y)<=R){
            m[i].stu+=3;
            if(m[i].breed>cur_t)
                m[i].breed+=3;
        }
}
inline void wp3(weapon k)
{
    for(int i=1;i<=tot;i++)
        if(m[i].x==k.x&&m[i].y==k.y)
            m[i].dead=1;
}
inline void wp4(weapon k)
{
    for(int i=1;i<=tot;i++)
        if(m[i].x==k.x&&m[i].y==k.y)
            m[i].sex^=1;
}
inline void trigger()
{
    weapon k=b[cur_w+1];
    while(k.t==cur_t){
        cur_w++;
        if(k.type==1)wp1(k);
        if(k.type==2)wp2(k);
        if(k.type==3)wp3(k);
        if(k.type==4)wp4(k);
        k=b[cur_w+1];
    }
}
inline void simulation(mouse &k)
{
    k.breed=-1;
    int d=k.pos,now=mp[k.x][k.y];
    if(now&bin[d]){
        k.x+=dx[d];
        k.y+=dy[d];
        return;
    }
    int l=(d+3)%4,r=(d+1)%4,b=(d+2)%4;
    if(now&bin[b])
        now-=bin[b];
    if(now==bin[l])
        k.pos=l;
    else if(now==bin[l]+bin[r]){
             k.turn^=1;
             if(k.turn)k.pos=l;
             else k.pos=r;
         }
    else k.pos=r;
}
inline void breed()
{
    int tp=0;
    for(int i=1;i<=tot;i++)
        if(!m[i].dead)
            m[++tp]=m[i];
    tot=tp;
    memset(num,0,sizeof(num));
    for(int i=1;i<=tot;i++)
        num[m[i].x][m[i].y]++;
    for(int i=1;i<=tot;i++)
        if(!m[i].stu&&m[i].breed==-1&&num[m[i].x][m[i].y]==2&&!m[i].grow&&!m[i].sex)
            for(int j=1;j<=tot;j++)
                if(!m[j].stu&&m[j].x==m[i].x&&m[j].y==m[i].y&&!m[j].grow&&m[j].sex){
                    m[i].stu+=3;
                    m[j].stu+=3;
                    m[i].breed=cur_t+2;m[j].breed=cur_t+2;
                    break;
                }
    for(int i=1;i<=tot;i++)
        if(m[i].breed==cur_t&&m[i].sex){
            for(int k=0;k<4;k++)
                if(bin[k]&mp[m[i].x][m[i].y]){
                    tot++;
                    m[tot].x=m[i].x;m[tot].y=m[i].y;
                    m[tot].breed=-1;
                    m[tot].dead=m[tot].turn=0;
                    m[tot].stu=0;
                    m[tot].grow=5;
                    m[tot].pos=k;
                    if(k==0||k==2)m[tot].sex=0;
                    else m[tot].sex=1;
                }
        }
}
int main()
{
    char ch[5];
    scanf("%d%d%d%d",&L,&R,&M,&n);
    R=R*R;
    for(int i=1;i<=M;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&mp[i][j]);
    scanf("%d",&tot);
    for(int i=1;i<=tot;i++){
        scanf("%d%d",&m[i].x,&m[i].y);
        scanf("%s",ch);
        if(ch[0]=='N')
            m[i].pos=0;
        if(ch[0]=='E')
            m[i].pos=1;
        if(ch[0]=='S')
            m[i].pos=2;
        if(ch[0]=='W')
            m[i].pos=3;
        scanf("%s",ch);
        if(ch[0]=='Y')m[i].sex=1;
        else m[i].sex=0;
        m[i].breed=-1;
    }
    scanf("%d%d",&P,&limit);
    for(int i=1;i<=P;i++){
        scanf("%d%d%d%d",&b[i].type,&b[i].t,&b[i].x,&b[i].y);
        if(b[i].type==3)
            b[i].t+=3;
    }
    sort(b+1,b+1+P);
    scanf("%d",&T);
    for(cur_t=0;cur_t<=T;cur_t++){
        trigger();//trigger weapons;
        breed();//breeding;
        if(tot>limit)
            {puts("-1");return 0;}
        if(cur_t!=T){//T->time limit;
            for(int i=1;i<=tot;i++){
                if(m[i].stu)
                    m[i].stu--;
                else{
                    simulation(m[i]);
                    if(!m[i].stu&&m[i].grow)
                        m[i].grow--;
                }
            }
        }
    }
    printf("%d\n",tot);
    return 0;
}

第一次寫190行+的模擬,果然代碼能力還是不足。。。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章