zoukankan      html  css  js  c++  java
  • FOJ2250 不可能弹幕结界

    Problem 2250 不可能弹幕结界

    Time Limit: 1000 mSec    Memory Limit : 65536 KB

    Problem Description

    咲夜需要穿过一片弹幕区,由于咲夜发动了符卡“The World”,所以弹幕是静止的。这片弹幕区以一个n*m的矩阵的形式给出。

    ‘.’表示这个位置是安全的,’x’表示这个位置上是有子弹的,禁止通行。咲夜每次能向左、右、下三个方向的相邻格子走,但是不能向上走。 同时由于时间有限,咲夜在进入每一行之后最多只能横向走k步。你可以简单地认为我们的目标就是从第0行走到第n+1行,起点和终点可以是在第0行和第n+1行的任意位置,当然第0行和第n+1行都是没有弹幕的。

    然而这是号称不可能的弹幕结界,所以咲夜很可能无法穿过这片弹幕,所以咲夜准备了一个只能使用一次的技能,纵向穿越,她可以从任意位置直接穿越到另外任意一行的同一个位置(所在列不变),当然她只能向下穿越,不能向上穿越。穿越的距离越远,耗费的资源自然越多,所以她想知道最短的穿越距离,才能使她成功通过这片弹幕区。

    Input

    输入包含多组数据。

    对于每组数据:

    第一行输入三个整数n,m,k,如上所述。

    接下下输入一个n×m的矩阵,’.’表示当前这格没有子弹,是安全的,’x’表示这各有子弹,禁止通行。

    N<=1000,k<=m<=1000

    Output

    对于每组数据输出一个整数,表示最短的穿越距离。

    Sample Input

    6 5 2 x.x.. ..xx. .xxx. xx.xx xx..x ..x.x 4 4 1 .xxx .xxx ...x xx.x

    Sample Output

    3 2

    Hint

    对于第一组样例,最优解是从第一行第二列走到第三行第一列,然后跳到第6行第一列,穿越距离为(6 – 3) = 3。

    分析:考虑从上往下走;

       状态转移为如果当前点能够到达,那么下一行这一列如果是‘.’的话,那么这个点左右可到达的范围也能到达;

       即if(ok(i,j))ok(i+1,l[i+1][j]~r[i+1][j]);这个标记差分即可;

       所以预处理每个点左右能到达的范围;

       从下往上也一样,最后找一下行间隔最小即可,注意边界;

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <bitset>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cassert>
    #define rep(i,m,n) for(i=m;i<=n;i++)
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define vi vector<int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    #define pii pair<int,int>
    #define sys system("pause")
    const int maxn=1e3+10;
    const int N=2e5+10;
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;}
    int n,m,k,t,l[maxn][maxn],r[maxn][maxn],dp[maxn],up[maxn][maxn],dw[maxn][maxn];
    char a[maxn][maxn];
    int main()
    {
        int i,j;
        while(~scanf("%d%d%d",&n,&m,&k))
        {
            rep(i,1,n)scanf("%s",a[i]+1);
            memset(dp,-1,sizeof(dp));
            memset(up,0,sizeof(up));
            memset(dw,0,sizeof(dw));
            rep(i,1,n)
            {
                rep(j,1,m)
                {
                    if(j==1)l[i][j]=j;
                    else l[i][j]=a[i][j-1]!='x'?l[i][j-1]:j;
                    if(l[i][j]<j-k)l[i][j]=j-k;
                }
                for(j=m;j>=1;j--)
                {
                    if(j==m)r[i][j]=j;
                    else r[i][j]=a[i][j+1]!='x'?r[i][j+1]:j;
                    if(r[i][j]>j+k)r[i][j]=j+k;
                }
            }
            rep(i,1,m)if(a[1][i]=='.')up[1][i]=1;
            rep(i,1,n)
            {
                if(i!=1)
                {
                    rep(j,1,m)up[i][j]+=up[i][j-1];
                }
                rep(j,1,m)
                {
                    if(up[i][j]&&a[i+1][j]=='.')up[i+1][l[i+1][j]]++,up[i+1][r[i+1][j]+1]--;
                }
            }
            rep(i,1,m)if(a[n][i]=='.')dw[n][i]=1;
            for(i=n;i>=1;i--)
            {
                if(i!=n)
                {
                    rep(j,1,m)dw[i][j]+=dw[i][j-1];
                }
                rep(j,1,m)
                {
                    if(dw[i][j]&&a[i-1][j]=='.')dw[i-1][l[i-1][j]]++,dw[i-1][r[i-1][j]+1]--;
                }
            }
            int ret=n+1;
            for(i=n;i>=1;i--)
            {
                rep(j,1,m)
                {
                    if(up[i][j])ret=min(ret,n+1-i);
                    if(up[i][j]&&dp[j]!=-1)ret=min(ret,dp[j]-i);
                    if(dw[i][j])dp[j]=i,ret=min(ret,i);
                }
            }
            rep(i,1,m)if(up[n][i])ret=0;
            printf("%d
    ",ret);
        }
        return 0;
    }
  • 相关阅读:
    n个元素进栈,有几种出栈方式
    The following IP can be used to access Google website
    一个未排序整数数组,有正负数,重新排列使负数排在正数前面,并且要求不改变原来的 相对顺序 比如: input: 1,7,-5,9,-12,15 ans: -5,-12,1,7,9,15 要求时间复杂度O(N),空间O(1) 。
    当今世界最受人们重视的十大经典算法
    指针
    变量作用域和生存期
    一篇文章搞清spark内存管理
    Spark的Shuffle是怎么回事
    一篇文章搞清spark任务如何执行
    scala这写的都是啥?一篇文章搞清柯里化
  • 原文地址:https://www.cnblogs.com/dyzll/p/6724727.html
Copyright © 2011-2022 走看看