poj 1071 Illusive Chase

题目大意:有一个m*n大小的房间与房间的描述,(x,y)=1代表该点不可通过或到达,(x,y)=0代表该点能通过或到达。然后给你若干个行动的描述,每一步按先后顺序排列,包含的参数有移动的最短距离,最长距离与方向。问房间有几个可能的起点,使其能够走完全部行动。

思路:令step[i]为第i步行动,dp[k][i][j]代表在第k步时从房间(i,j)为起点开始行动,能否走完剩下的行动。若能则赋为1,反之为0;则有递推关系dp[k-1][i][j]=1,如果dp[k][i+step[k]][j+step[k]]=1,反之为0。从后到前反推,最后dp[0][i][j]中1的个数即为可能的起点数。

 

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

struct Step
{
    int min_step,max_step;
    int direction;
}step[5005];

bool dp1[105][105],dp2[105][105];
int map[105][105];
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};

int main(int argc, char** argv)
{
    int t,m,n,i,j,k,left,right,step_num,cnt,xx,yy,ans;
    char orientation;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d%d",&m,&n);
        for (i=1;i<=m;i++)
            for (j=1;j<=n;j++)
                scanf("%d",&map[i][j]);
        for (i=0;i<=m+1;i++)
            map[i][0]=map[i][n+1]=1;
        for (j=0;j<=n+1;j++)
            map[0][j]=map[m+1][j]=1;
        step_num=0;
        while (scanf("%d%d",&left,&right)==2 && left!=0 && right!=0)
        {
            scanf(" %c",&orientation);
            step_num++;
            step[step_num].min_step=left;
            step[step_num].max_step=right;
            if (orientation=='R')
                step[step_num].direction=2;
            else if (orientation=='L')
                step[step_num].direction=3;
            else if (orientation=='U')
                step[step_num].direction=1;
            else
                step[step_num].direction=0;
        }
        memset(dp2,false,sizeof(dp2));
        for (i=1;i<=m;i++)
            for (j=1;j<=n;j++)
                if (map[i][j]==0)
                    dp2[i][j]=true;
        for (k=step_num;k>=1;k--)
        {
            memset(dp1,false,sizeof(dp1));
            for (i=1;i<=m;i++)
                for (j=1;j<=n;j++)
                    if (dp2[i][j])
                    {
                        xx=i;
                        yy=j;
                        for (cnt=1;cnt<step[k].min_step;cnt++)
                        {
                            xx+=dx[step[k].direction];
                            yy+=dy[step[k].direction];
                            if (map[xx][yy]==1)
                                break;
                        }
                        if (cnt>=step[k].min_step)
                            for (cnt=step[k].min_step;cnt<=step[k].max_step;cnt++)
                            {
                                xx+=dx[step[k].direction];
                                yy+=dy[step[k].direction];
                                if (map[xx][yy]==0)
                                    dp1[xx][yy]=true;
                                else
                                    break;
                            }
                    }
            memcpy(dp2,dp1,sizeof(dp1));
        }
        ans=0;
        for (i=1;i<=m;i++)
            for (j=1;j<=n;j++)
                if (dp1[i][j])
                    ans++;
        printf("%d\n",ans);
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值