BZOJ2548 [CTSC2002] 灭鼠行动

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2548 [CTSC2002] 灭鼠行动相关的知识,希望对你有一定的参考价值。

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2548

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的老鼠数目。

大模拟什么的最恶心了

难的不是coding,而是debugging

如果你从网上下载到了数据,那么请把第7个点的答案由79改为22

技术分享

技术分享
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cmath>
  6 #define rep(i,l,r) for(int i=l; i<=r; i++)
  7 #define clr(x,y) memset(x,y,sizeof(x))
  8 using namespace std;
  9 const int maxn = 60;
 10 const int bin[4] = {1,2,4,8};
 11 const int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
 12 inline int read(){
 13     int ans = 0, f = 1;
 14     char c = getchar();
 15     for(; !isdigit(c); c = getchar())
 16     if (c == -) f = -1;
 17     for(; isdigit(c); c = getchar())
 18     ans = ans * 10 + c - 0;
 19     return ans * f;
 20 }
 21 struct Mouse{
 22     int x,y,dir,grow,frez,time,breed;
 23     bool sex,dead;
 24 }m[110];
 25 struct Weapon{
 26     int x,y,type,time;
 27 }w[110];
 28 int L,R,M,n,P,K,head=0,cur,limit,Time,c[maxn][maxn],num[maxn][maxn];
 29 bool mark[maxn][maxn];
 30 char ch[10];
 31 inline double getdis(int x1,int y1,int x2,int y2){
 32     return sqrt((x1-x2) * (x1-x2) + (y1-y2) * (y1-y2));
 33 }
 34 inline void flush(){
 35     int cnt = 0;
 36     rep(i,1,K) if (!m[i].dead) m[++cnt] = m[i];
 37     K = cnt;
 38 }
 39 void expose(){
 40     rep(p,1,P){
 41         Weapon now = w[p];
 42         if (now.time == cur)
 43         switch(now.type){
 44             case 1:
 45                 clr(mark,0); mark[now.x][now.y] = 1;
 46                 rep(i,0,3){
 47                     int nowx = now.x, nowy = now.y, dis = 0;
 48                     while (c[nowx][nowy] & bin[i]){
 49                         nowx += dir[i][0]; nowy += dir[i][1]; dis++;
 50                         if (dis > L) break;
 51                         mark[nowx][nowy] = 1;
 52                     }
 53                 }
 54                 rep(i,1,K){
 55                     if (mark[m[i].x][m[i].y]) m[i].dead = 1;
 56                 }
 57             break;
 58             case 2:
 59                 rep(i,1,K){
 60                     if (getdis(now.x,now.y,m[i].x,m[i].y) <= R){
 61                         m[i].frez += 3;
 62                         if (m[i].breed > cur) m[i].breed += 3;
 63                     }
 64                 }
 65             break;
 66             case 3:
 67                 rep(i,1,K)
 68                 if (m[i].x == now.x && m[i].y == now.y)
 69                 m[i].dead = 1;
 70             break;
 71             case 4:
 72                 rep(i,1,K)
 73                 if (m[i].x == now.x && m[i].y == now.y)
 74                 m[i].sex ^= 1;
 75             break;
 76         }
 77     }
 78 }
 79 void breed(){
 80     flush();
 81     clr(num,0);
 82     rep(i,1,K) num[m[i].x][m[i].y]++;
 83     rep(i,1,K){
 84         if (!m[i].grow && !m[i].frez && m[i].breed == -1 && !m[i].sex && num[m[i].x][m[i].y] == 2){
 85             rep(j,1,K) if (!m[j].grow && !m[j].frez && m[j].sex && m[j].x == m[i].x && m[j].y == m[i].y){
 86                 m[i].frez += 3; m[j].frez += 3;
 87                 m[i].breed = m[j].breed = cur + 2;
 88                 break;
 89             }
 90         }
 91     }
 92     rep(i,1,K){
 93         if (m[i].breed == cur && m[i].sex){
 94             rep(j,0,3){
 95                 if (bin[j] & c[m[i].x][m[i].y]){
 96                     K++; m[K].x = m[i].x; m[K].y = m[i].y;
 97                     m[K].frez = m[K].time = m[K].dead = 0;
 98                     m[K].dir = j; m[K].grow = 5; m[K].breed = -1;
 99                     if (j == 0 || j == 2) m[K].sex = 0; else m[K].sex = 1;
100                 }
101             }
102         }
103     }
104 }
105 void move(Mouse &x){
106     x.breed = -1; int now = c[x.x][x.y];
107     if (now & bin[x.dir]){
108         x.x += dir[x.dir][0]; x.y += dir[x.dir][1];
109         return;
110     }
111     int r = (x.dir + 1) % 4, l = (x.dir + 3) % 4, b = (x.dir + 2) % 4;
112     if (now & bin[b]) now -= bin[b];
113     if (!now){
114         x.dir = r; return;
115     }
116     if (now == bin[l]) x.dir = l;
117     else if (now == bin[r]) x.dir = r;
118     else{
119         x.time++;
120         if (x.time & 1) x.dir = l;
121         else x.dir = r;
122     }
123 }
124 int main(){
125     L = read(); R = read(); M = read(); n = read();
126     rep(i,1,M) rep(j,1,n) c[i][j] = read();
127     K = read();
128     rep(i,1,K){
129         m[i].x = read(); m[i].y = read();
130         scanf("%s",ch);
131         if (ch[0] == N) m[i].dir = 0; else if (ch[0] == E) m[i].dir = 1;
132         else if (ch[0] == S) m[i].dir = 2; else if (ch[0] == W) m[i].dir = 3;
133         scanf("%s",ch); m[i].sex = (ch[0] == Y);
134         m[i].breed = -1;
135     }
136     P = read(); limit = read();
137     rep(i,1,P){
138         w[i].type = read(); w[i].time = read(); w[i].x = read(); w[i].y = read();
139         if (w[i].type == 3) w[i].time += 3;
140     }
141     Time = read();
142     for(cur=0; cur<=Time; cur++){
143         expose();
144         breed();
145         if (K > limit){
146             printf("-1\n"); return 0;
147         }
148         if (cur != Time){
149             rep(i,1,K)
150             if (m[i].frez) m[i].frez--;
151             else{
152                 move(m[i]);
153                 if (m[i].grow) m[i].grow--;
154             }
155         }
156     }
157     printf("%d\n",K);
158     return 0;
159 }
View Code

 

以上是关于BZOJ2548 [CTSC2002] 灭鼠行动的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2547: [Ctsc2002]玩具兵

BZOJ 3555: [Ctsc2014]企鹅QQ

bzoj——3555: [Ctsc2014]企鹅QQ

bzoj3557: [Ctsc2014]随机数

BZOJ4068 : [Ctsc2015]app

BZOJ-3555: [Ctsc2014]企鹅QQ (hash)