poj 1104 Robbery

来源:互联网 发布:珊蔻·娜赤娅克 知乎 编辑:程序博客网 时间:2024/05/19 18:17

/*

递推题,好几处需要证明,从而可以简化问题,助于理解

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

2)开始递推扫描,经证明,只要一次正向和一次反向递推就可以了,以正向递推为例(反向递推同理),对于时刻

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处可能会有盗贼

3)几点说明,均已经证明过:

    a) 如果有任何一个时刻全部为1,则通过递推所有时刻都会变成1,所以只要有一个时刻全部格子都是1的话,则

        说明盗贼已经逃跑了

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

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

*/

 

#include <iostream>
#include <memory>
#define MAX_N 105
using namespace std;

bool tag[MAX_N + 1][MAX_N + 1][MAX_N + 1];
int dir[5][2] = {{0, 0}, {-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int res[MAX_N + 1][2]; // -1, all one -2, not unique zero, >=1 unique position
int W, H, T, N, ti, LI, TI, RI, BI, lastT = INT_MIN;


bool inRange(int curH, int curW)
{
    return (curH >= 1 && curH <= H && curW >= 1 && curW <= W);
}

//true: this should be zero
bool check(int curH, int curW, int curT, int pT)
{
    if(tag[curT][curH][curW])
        return false;
    int d, nH, nW;
    for(d = 0; d < 5; d++)
    {
        nH = curH + dir[d][0];
        nW = curW + dir[d][1];
        if(inRange(nH, nW))
        {
            if(!tag[pT][nH][nW])
                return false;
        }
    }
    tag[curT][curH][curW] = true;
    return true;
}
int main()
{
    int i, r, c, d, seq = 0;
    while(cin>>W>>H>>T && !(W == 0 && H == 0 && T== 0))
    {
        cin>>N;
        seq++;
        lastT = INT_MIN;
        memset(tag, false, sizeof(tag));
        for(i = 1; i <= N; i++)
        {
            cin>>ti>>LI>>TI>>RI>>BI;
            for(r = TI; r <= BI; r++)
            {
                for(c = LI; c <= RI; c++)
                    tag[ti][r][c] = true;
            }
            if(ti > lastT)
                lastT = ti;
        }
        bool changed = true;
        for(d = 0; d < 2; d++)
        {
            for(i = 1; i <= T; i++)
            {
                for(r = 1; r <= H; r++)
                {
                    for(c = 1; c <= W; c++)
                    {
                        if(d == 0 && i != 1)
                            check(r, c, i, i - 1);
                        else if(d == 1)
                            check(r, c, T - i + 1, T - i + 2);
                    }
                }
            }
        }
        bool allOne = true, allallOne = true, allMult = true;
        memset(res, 0, sizeof(res));
        for(i = 1; i <= T; i++)
        {
            allOne = true;
            bool con = true;
            for(r = 1; r <= H && con; r++)
            {
                for(c = 1; c <= W && con; c++)
                {
                    if(!tag[i][r][c])
                    {
                        allOne = false;
                        if(res[i][0] == 0)
                        {
                            res[i][0] = r;
                            res[i][1] = c;
                        }
                        else if(res[i][0] >= 1)
                        {
                            res[i][0] = -2;
                            con = false;
                        }
                    }
                }
            }
            if(allOne)
            {
                res[i][0] = -1;
            }else    allallOne = false;
           
            if(res[i][0] != -2)
                allMult = false;
        }
        cout<<"Robbery #"<<seq<<":"<<endl;
        if(allallOne)
            cout<<"The robber has escaped."<<endl;
        else if(allMult)
            cout<<"Nothing known."<<endl;
        else
        {
            for(i = 1; i <= T; i++)
            {
                if(res[i][0] >= 1)
                {
                    cout<<"Time step "<<i<<": ";
                    cout<<"The robber has been at "<<res[i][1]<<","<<res[i][0]<<"."<<endl;
                }
            }
        }
        cout<<endl;
    }
    return 0;
}