zoukankan      html  css  js  c++  java
  • 【BZOJ 5048 塌陷的牧场】

    Time Limit: 25 Sec  Memory Limit: 256 MB
    Submit: 77  Solved: 34
    [
    Submit][Status][Discuss]

     

    Description

    农夫小Q将他的奶牛们饲养在一个长n宽m的矩形网格牧场中。行从上到下依次编号为1到n,列从左往右依次编号为1

    到m。为了防止奶牛们逃跑,小Q在牧场外圈安装了一排电网,只要奶牛走出这个n*m的矩形,就会触电死去。在牧

    场中,有e个格子塌陷了,一旦奶牛踩在上面,就会掉下去摔死。小Q为了饲养尽可能多的奶牛,在每个没有塌陷的

    格子上,都饲养着一头奶牛。tangjz偷走了小Q的口哨,并用口哨向奶牛们依次施放了q条指令,每条指令包含两个

    参数d和k,d表示上下左右之一的方向,k表示前进步数。发出指令后,每头奶牛都会听话地执行指令,甚至会因此

    丧生。所有奶牛移动完毕之后,tangjz才会施放下一条指令。请写一个程序统计每条指令中小Q损失了多少头奶牛

    Input

    第一行包含4个正整数n,m,e,q(1<=n,m,q<=2000,0<=e<=min(nm,2000))

    分别表示牧场的长宽、塌陷的格子数以及指令数。

    接下来e行,每行两个正整数x_i,y_i(1<=x_i<=n,1<=y_i<=m)

    表示每个塌陷格子的坐标。输入数据保证每个格子不会被描述多次。

    接下来q行,每行包含一个字符d和一个正整数k(1<=k<=2000)

    描述每条指令。其中UDLR分别表示上下左右。

    Output

    输出q行,每行一个整数,即第i条指令中损失的奶牛数量。

    Sample Input

    3 5 3 4
    1 4
    2 2
    3 3
    R 2
    L 1
    D 2
    U 1

    Sample Output

    10
    0
    2
    0

    题解:

          ①观察数据发现障碍物非常少,不超过2000,因此将移动牛反过来换成移动障碍物。

          ②但是每次移动每个障碍物并杀死牛这种暴力时间复杂度为:O(n3),需要优化:

          ③使用链表优化,分别表示四个方向上指向的最近的没有被杀死的牛的位置。

          ④链表的实现有的人说是并查集……QAQ

    #include<cstdio>
    #define Fa fa[_]
    #define go(i,a,b) for(int i=a;i<=b;i++)
    const int N=2003;struct P{int x,y;}a[10010];
    int n,m,e,q,ans,k,fa[5][N][N],_;bool dead[N][N];char c;
    void Kill(int x,int y)
    {
        if(dead[x][y])return;ans+=(dead[x][y]=1);
        fa[0][x][y]--;fa[1][x][y]++;fa[2][x][y]--;fa[3][x][y]++;
    }
    int find01(int x,int y){return Fa[x][y]==x?x:Fa[x][y]=find01(Fa[x][y],y);}
    int find23(int x,int y){return Fa[x][y]==y?y:Fa[x][y]=find23(x,Fa[x][y]);}
    
    void Up(){_=0;go(i,1,e)
        {
            int x=a[i].x,y=a[i].y;a[i].x-=k;
            if(y<1||y>m||x<1)continue;if(x>n)x=n;
            while((x=find01(x,y))>=1&&x>=a[i].x)Kill(x,y);    
        }
    }
    void Down(){_=1;go(i,1,e)
        {
            int x=a[i].x,y=a[i].y;a[i].x+=k;
            if(y<1||y>m||x>n)continue;if(x<1)x=1;
            while((x=find01(x,y))<=n&&x<=a[i].x)Kill(x,y);
        }
    }
    void Left(){_=2;go(i,1,e)
        {
            int x=a[i].x,y=a[i].y;a[i].y-=k;
            if(x<1||x>n||y<1)continue;if(y>m)y=m;
            while((y=find23(x,y))>=1&&y>=a[i].y)Kill(x,y); 
        }
    }
    void Right(){_=3;go(i,1,e)
        {
            int x=a[i].x,y=a[i].y;a[i].y+=k;
            if(x<1||x>n||y>m)continue;if(y<1)y=1;
            while((y=find23(x,y))<=m&&y<=a[i].y)Kill(x,y);
        }
    }
    int main()
    {	
        scanf("%d%d%d%d",&n,&m,&e,&q);
        go(i,0,n+1)go(j,0,m+1)fa[0][i][j]=fa[1][i][j]=i,fa[2][i][j]=fa[3][i][j]=j;
        go(i,1,e)scanf("%d %d",&a[i].x,&a[i].y),Kill(a[i].x,a[i].y);
        go(i,1,n)a[++e].x=i,a[e].y=0,a[++e].x=i,a[e].y=m+1;
        go(i,1,m)a[++e].x=0,a[e].y=i,a[++e].x=n+1,a[e].y=i;
        while(ans=0,q--&&scanf(" %c%d",&c,&k))
    	{
    		c=='U'?Down(),1:1,c=='D'?Up(),1:1,c=='R'?Left(),1:1,c=='L'?Right(),1:1;
            printf("%d
    ",ans);
    	}return 0;
    }//Paul_Guderian

    回首往事我明白了他曾叮咛的,所有那些平淡无味的话语.

    那年我五岁,爸爸对我说,学一点东西,否则你会一事无成。————汪峰《那年我五岁》

  • 相关阅读:
    GoogleTest初探(2)
    GoogleTest初探(1)
    GoogleMock初探(0)
    GoogleTest初探(0)
    [leetcode] 二叉树的前序,中序,后续,层次遍历
    关于phpmyadmin报403错误forbidden
    如何使用Fiddler抓取Android手机数据请求
    安全性测试之安装包测试
    二代身份证号码编码规则
    Excel导入功能测试用例整理
  • 原文地址:https://www.cnblogs.com/Damitu/p/7657084.html
Copyright © 2011-2022 走看看