UVALive-7297-Hounded by Indecision

来源:互联网 发布:域名主机购买多少钱 编辑:程序博客网 时间:2024/06/16 10:43

题目链接:点击打开链接

题目大意:
给你一个N*M的矩阵,里面有一个小偷,一个警察和一条警犬以及若干个出口,警察在追捕小偷。每次小偷和警察只能在水平或者竖直方向上移动一格,小偷和警察同时移动。起初警察和警犬在一起追捕,当警察到达小偷到达过的地点时,警犬则会以2倍的速度追赶小偷,而警察速度不变。问小偷能不能一定有办法在被追到之前离开矩阵。
解题思路:
题目就是让你搜索出口,并且看是否有方案满足不被警察追到。
其实我们只要解决如何判断某一个点能不能走,如果这个解决了,那么就依次判断下去就可以了,最后看是否可以到达出口。(记为A点)
一:收先可以判断的是小偷必须在警察之前到达A点(要保证一定不被抓),计小偷到A的时间为T1,警察到A点的时间为T2,则T2>T1;
二:满足条件一后,当小偷到达A点以后,由于当警察到达A点之后,警犬会以两倍的速度追赶,所以之后小偷又一个最大的移动时间。即超过该时间会被警犬追上。
计算该时间:当警察到达A点时(距离小偷离开A点已经有T2-T1的时间了),小偷领先警察T2-T1,之后警犬以小偷2倍的速度追赶,可以知道警犬会花费T2-T1的时间追上小偷。所以小偷到达A点以后最大的移动时间为Limit_Time=2*(T2-T1);
三:假设小偷在前一个点剩余的最大移动时间为T,那么在A点小偷的最大剩余移动时间为T-1,那么要保证不被警察抓到,在A点的剩余时间就应该取条件二与T-1的较小值,即Limit_Time=min(T-1,Limit_Time),然后每搜到一个点记录在该点的最大剩余时间。当重复搜到某个点时,如果后者可以使最大剩余时间变大(说明有更优的方案到达该点),则入队,并更新当前点最多剩余时间,否则不入队。
四:判断搜索。
代码:
#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cstdio>#include<queue>using namespace std;char mp[55][55];int xT,yT,xK,yK,n,m;int dir[4][2]={0,1,1,0,0,-1,-1,0};int vis[55][55];int Ksteps[55][55];int Tsteps[55][55];bool check(int x,int y){    if(x<0||x>n||y<0||y>m)return 0;    return 1;}struct node{    int x,y;    int steps;    int Left_steps;}beg,in,out;void K_BFS(){    memset(Ksteps,-1,sizeof Ksteps);    beg.x=xK;beg.y=yK;beg.steps=0;    Ksteps[xK][yK]=0;    queue<node>Q;    Q.push(beg);    while(!Q.empty()){        out=Q.front();        Q.pop();        for(int i=0;i<4;i++){            in.x=out.x+dir[i][0];            in.y=out.y+dir[i][1];            in.steps=out.steps+1;            if(!check(in.x,in.y))continue;            if(Ksteps[in.x][in.y]!=-1)continue;            if(mp[in.x][in.y]=='X')continue;            Ksteps[in.x][in.y]=in.steps;            Q.push(in);        }    }}bool T_BFS(){    memset(Tsteps,0,sizeof Tsteps);    beg.x=xT;beg.y=yT;beg.steps=0;    beg.Left_steps=2*Ksteps[xT][yT];    Tsteps[xT][yT]=2*Ksteps[xT][yT];    queue<node>Q;    Q.push(beg);    while(!Q.empty()){        out=Q.front();        Q.pop();        if(mp[out.x][out.y]=='E')return true;        for(int i=0;i<4;i++){            in.x=out.x+dir[i][0];            in.y=out.y+dir[i][1];            in.steps=out.steps+1;            if(!check(in.x,in.y))continue;            if(mp[in.x][in.y]=='X')continue;            if(in.steps>=Ksteps[in.x][in.y])continue;            in.Left_steps=min(out.Left_steps-1,2*Ksteps[in.x][in.y]-2*in.steps);            if(in.Left_steps<=Tsteps[in.x][in.y])continue;//与该点的最大剩余做比较,变大才入队            Tsteps[in.x][in.y]=in.Left_steps;            Q.push(in);        }    }    return false;}int main(){//    freopen("in.txt","r",stdin);    char ch;    while(~scanf("%d%d",&m,&n)&&(n||m)){        getchar();        for(int i=0;i<n;i++){             for(int j=0;j<m;j++){                 ch=getchar();                 mp[i][j]=ch;                 if(ch=='T'){xT=i;yT=j;}                 if(ch=='K'){xK=i;yK=j;}            }            getchar();         }         K_BFS();         if(T_BFS())printf("KEEP IT\n");         else printf("DROP IT\n");    }    return 0;}
开始写BFS()或者DFS()的题目的入门题的时候,感觉好像挺简单的(虽然现在的可能还是比较水,但是感觉不那么水了),就模板一套上去就可以了,然后就是什么BFS()+DFS()这类的,想想看也还好,接着碰到一些什么状态压缩(第一次碰到的时候)......卧槽!还有这种操作?!。总之搜索还是很灵活的,要好好体会。
原创粉丝点击