AcWing4309. 消灭老鼠

Posted 算法第一深情

tags:

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

目录

1、AcWing4309. 消灭老鼠

2、只有你自己不断进步,才能救赎自己!!!


1、AcWing4309. 消灭老鼠

题目通道

约翰的农场可以看作一个二维平面。

农场中有 n 个老鼠,在毁坏着农田。

第 i个老鼠的位置坐标为 (xi,yi)。

不同老鼠可能位于同一位置。

在 (x0,y0)处,装有一个双向发射的激光枪,该位置没有老鼠。

激光枪每次发射都可以将穿过点 (x0,y0)的某一条直线上的所有老鼠都消灭掉。

请问,为了消灭所有老鼠,至少需要激光枪发射几次。

输入格式

第一行包含三个整数 n,x0,y0,表示共有 n 只老鼠,激光枪的位置为 (x0,y0)。

接下来 n行,每行包含两个整数 xi,yi,表示第 i 只老鼠的位置为 (xi,yi)。

输出格式

一个整数,表示激光枪的最少发射次数。

数据范围

前 55 个测试点满足 1≤n≤5。
所有测试点满足 1≤n≤1000,−1e4≤xi,yi≤1e4。

输入样例1:

4 0 0
1 1
2 2
2 0
-1 -1

输出样例1:

2

输入样例2:

2 1 2
1 1
1 0

输出样例2:

1

题目疑问:

1,如何表示/储存数据

2,怎样完整求到答案 

 题目分析:

1,因为此题涉及到了整个坐标问题,所以用二维数组求解会非常的麻烦,那么我们就要想其他的办法,题目中“激光枪每次发射都可以将穿过点 (x0,y0)的某一条直线上的所有老鼠都消灭掉”,那么我们就可以利用斜率来求了。有几个不同的斜率,我们就需要发射激光几次,这样就求的答案了。

2,求斜率我们不能直接用坐标相除,因为可能会出现无穷的结果,其实我们也可以坐标化到最简,最终坐标相同的,斜率也会相同,我们用set储存最简坐标S.insert(x,y); //储存不同的斜率

知识点:STL set,最大公约数, 

#include <bits/stdc++.h>
#include <algorithm>
#include <set>
#define x first           //运用pair<>的标准模板
#define y second
using namespace std;
typedef pair<int,int>PII;//定义pair<>,它的作用是可以储存(x,y)这样的点
set<PII> S;              //用set容器储存
int n,x2,y2;
int gcd(int a,int b)     //求最大公约数模板

    return b?gcd(b,a%b):a;

int main()
    scanf("%d%d%d",&n,&x2,&y2);
    while(n--)
        int x,y;
        scanf("%d%d",&x,&y);
        x-=x2,y-=y2;     //将(x,y)置于原点
        int d=gcd(x,y);  //
        x/=d,y/=d;       //化简约分
        if(x<0)x=-x,y=-y;//将左半部的坐标映射到右半部分,因为题目中“激光枪每次发射都可以将穿过点 (x0,y0)
                         //的某一条直线上的所有老鼠都消灭掉”
        S.insert(x,y); //储存不同的斜率
    
    cout<<(int)S.size(); //
    return 0;

2、只有你自己不断进步,才能救赎自己!!!

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

 

以上是关于AcWing4309. 消灭老鼠的主要内容,如果未能解决你的问题,请参考以下文章

Acwing第 41 场周赛完结

8.14-T2捕老鼠(cat)

汕头市队赛SRM15

算法:老鼠走迷宫问题

贪心算法与老鼠走迷宫

Java与算法之 - 老鼠走迷宫(深度优先算法)