1104:Robbery

描述

Inspector Robstop is very angry. Last night, a bank has been robbed and the robber has not been caught. And this happened already for the third time this year, even though he did everything in his power to stop the robber: as quickly as possible, all roads leading out of the city were blocked, making it impossible for the robber to escape. Then, the inspector asked all the people in the city to watch out for the robber, but the only messages he got were of the form "We don't see him."
But this time, he has had enough! Inspector Robstop decides to analyze how the robber could have escaped. To do that, he asks you to write a program which takes all the information the inspector could get about the robber in order to find out where the robber has been at which time.

Coincidentally, the city in which the bank was robbed has a rectangular shape. The roads leaving the city are blocked for a certain period of time t, and during that time, several observations of the form "The robber isn't in the rectangle Ri at time ti" are reported. Assuming that the robber can move at most one unit per time step, your program must try to find the exact position of the robber at each time step.

Robstop 探长很生气。昨天晚上,一家银行被抢劫了,抢劫犯还没有被抓住。这已经是今年第三次发生了,尽管他竭尽全力去阻止抢劫犯: 尽快地,所有通往城市的道路都被封锁,使得抢劫犯无法逃脱。然后,检查员要求城里所有的人都小心那个抢劫犯,但是他收到的唯一信息是“我们没有看到他”但是这一次,他受够了!Robstop 探长决定分析一下劫匪是如何逃脱的。为了做到这一点,他要求你编写一个程序,该程序将检查员能够获得的有关劫匪的所有信息都记录下来,以便找出劫匪在何时何地出现过。巧合的是,银行被抢劫的城市是一个长方形。离开城市的道路被封锁了一段时间,在这段时间里,有几个关于“强盗在时间 t 不在矩形里”的观察报告。假设强盗每个时间步骤最多只能移动一个单位,那么程序必须尝试在每个时间步骤中找到强盗的确切位置。

输入
The input contains the description of several robberies. The first line of each description consists of three numbers W, H, t (1 <= W,H,t <= 100) where W is the width, H the height of the city and t is the time during which the city is locked.

The next contains a single integer n (0 <= n <= 100), the number of messages the inspector received. The next n lines (one for each of the messages) consist of five integers ti, Li, Ti, Ri, Bi each. The integer ti is the time at which the observation has been made (1 <= ti <= t), and Li, Ti, Ri, Bi are the left, top, right and bottom respectively of the (rectangular) area which has been observed. (1 <= Li <= Ri <= W, 1 <= Ti <= Bi <= H; the point (1, 1) is the upper left hand corner, and (W, H) is the lower right hand corner of the city.) The messages mean that the robber was not in the given rectangle at time ti.

The input is terminated by a test case starting with W = H = t = 0. This case should not be processed.

输入包含几起抢劫案的描述。每个描述的第一行由三个数字 W,H,t (1 < = W,H,t < = 100)组成,其中 W 是宽度,H 是城市的高度,t 是城市被锁定的时间。下一个包含单个整数 n (0 < = n < = 100) ,即检查器接收到的消息数。接下来的 n 行(每条消息一行)由五个整数 Ti、 Li、 Ti、 Ri、 Bi 组成。整数 Ti 是观察的时间(1 < = Ti < = t) ,Li、 Ti、 Ri、 Bi 分别是观察到的(矩形)区域的左、上、右和底部。(1 < = Li < = Ri < = W,1 < = Ti < = Bi < = H; 点(1,1)是城市的左上角,(W,H)是城市的右下角。)这些信息意味着劫匪当时不在给定的矩形内。输入由以 W = H = t = 0开始的测试用例终止。这个案子不应该被处理。

输出
For each robbery, first output the line "Robbery #k:", where k is the number of the robbery. Then, there are three possibilities:

If it is impossible that the robber is still in the city considering the messages, output the line "The robber has escaped."

In all other cases, assume that the robber really is in the city. Output one line of the form "Time step : The robber has been at x,y." for each time step, in which the exact location can be deduced. (x and y are the column resp. row of the robber in time step .) Output these lines ordered by time .

If nothing can be deduced, output the line "Nothing known." and hope that the inspector will not get even more angry.

Output a blank line after each processed case.

对于每起抢劫案,首先输出行“ Robbert # k:”,其中 k 是抢劫案件的编号。然后,有三种可能性: 如果不可能强盗仍然在城市考虑消息,输出行“强盗已经逃脱。在其他情况下,假设劫匪真的在城里。输出一行形式的“时间步骤: 强盗已经在 x,y。”对于每个时间步骤,其中确切的位置可以推断出来。(x 和 y 是列 rep。抢劫犯在时间步骤中的行。)按时间顺序输出这些行。如果无法推导出任何结果,则输出“ Nothing known”行,希望检查员不要再生气了。在每个处理过的案例后输出一个空行。

样例输入
4 4 5
4
1 1 1 4 3
1 1 1 3 4
4 1 1 3 4
4 4 2 4 4
10 10 3
1
2 1 1 10 10
0 0 0

样例输出
Robbery #1:
Time step 1: The robber has been at 4,4.
Time step 2: The robber has been at 4,3.
Time step 3: The robber has been at 4,2.
Time step 4: The robber has been at 4,1.

Robbery #2:
The robber has escaped.

来源
Mid-Central European Regional Contest 1999


分析

本题数据范围不大, W, H, t (1 <= W,H,t <= 100)。可以用暴力解决,建议递推。 

首先根据输入对tag数组进行设置,处于输入范围内的地方填入1,表示此处不可能出现盗贼,其他地方均填为0

开始递推扫描,只要一次正向和一次反向递推就可以了,以正向递推为例(反向递推同理),对于时刻 t 的x,y处,如果已经为1则不用处理,否则,考虑t-1时刻的(x, y), (x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)五个位置,如果有一个位置为0,则tag[t][x][y]也为0(很好理解,因为这表示t时刻的x,y处可能会有盗贼

几点说明:

1. 如果有任何一个时刻全部为1,则通过递推所有时刻都会变成1,所以只要有一个时刻全部格子都是1的话,则说明盗贼已经逃跑了

2.如果第一点不满足,则如果所有时刻都不止一个格子为0,则无从判断盗贼的位置,输出Nothing known.

3.否则,说明存在可以判断盗贼位置的时刻,输出坐标即可


代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 110
 
int W, H, T, n;
bool notv[maxn][maxn][maxn];
 
bool cant(int t, int x, int y, int tadd)
{
    if (x>0 && !notv[t+tadd][x-1][y]) return false;
    if (x<W-1 && !notv[t+tadd][x+1][y]) return false;
    if (y>0 && !notv[t+tadd][x][y-1]) return false;
    if (y<H-1 && !notv[t+tadd][x][y+1]) return false;
    if (!notv[t+tadd][x][y]) return false;
    return true; 
}
 
int main()
{
    int cs=0, t, x1, y1, x2, y2;
    int maybe[maxn], xx[maxn], yy[maxn];
    bool escape, know;
    
    while (scanf("%d%d%d", &W, &H, &T)==3 && W && H && T)
    {
        printf("Robbery #%d:\n", ++cs);
        scanf("%d", &n);
        memset(notv, 0, sizeof(notv));
        memset(maybe, 0, sizeof(maybe));
        escape=false;
        for (int i=0; i<n; i++)
        {
            scanf("%d%d%d%d%d", &t, &x1, &y1, &x2, &y2);
            for (int x=x1-1; x<x2; x++)         //根据输入判断强盗肯定不在的位置 
                for (int y=y1-1; y<y2; y++)
                    notv[t-1][x][y]=true;
        }
        for (int t=1; t<T; t++)                             //正着一遍floodfill强盗肯定不在的位置 
            for (int x=0; x<W; x++)
                for (int y=0; y<H; y++)
                    if (!notv[t][x][y] && cant(t, x, y, -1))
                        notv[t][x][y]=true;
        
        for (int x=0; x<W; x++)
            for (int y=0; y<H; y++)
            {
                if (!notv[T-1][x][y])
                {
                    maybe[T-1]++; xx[T-1]=x; yy[T-1]=y;
                }
            }
        if (maybe[T-1]==0) escape=true;                      //判断最后时刻是否逃走,是的话结束 
        for (int t=T-2; t>=0 && !escape; t--)                 //反着一遍floodfill强盗肯定不在的位置
        {
            for (int x=0; x<W; x++)
                for (int y=0; y<H; y++)
                {
                    if (!notv[t][x][y] && cant(t, x, y, +1))
                        notv[t][x][y]=true;
                    if (!notv[t][x][y])
                    {
                        maybe[t]++; xx[t]=x; yy[t]=y;
                    }
                }
            if (maybe[t]==0) escape=true;
        }
        if (escape)
            printf("The robber has escaped.\n\n");
        else
        {
            know=false;
            for (int t=0; t<T; t++)
                if (maybe[t]==1)
                {
                    know=true;
                    printf("Time step %d: The robber has been at %d,%d.\n", t+1, xx[t]+1, yy[t]+1);
                }
            if (!know) printf("Nothing known.\n");
            printf("\n");
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值