zoukankan      html  css  js  c++  java
  • BZOJ 1207

    1207: [HNOI2004]打鼹鼠

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 3089  Solved: 1499
    [Submit][Status][Discuss]

    Description

    鼹鼠是一种很喜欢挖洞的动物,但每过一定的时间,它还是喜欢把头探出到地面上来透透气的。根据这个特点阿Q编写了一个打鼹鼠的游戏:在一个n*n的网格中,在某些时刻鼹鼠会在某一个网格探出头来透透气。你可以控制一个机器人来打鼹鼠,如果i时刻鼹鼠在某个网格中出现,而机器人也处于同一网格的话,那么这个鼹鼠就会被机器人打死。而机器人每一时刻只能够移动一格或停留在原地不动。机器人的移动是指从当前所处的网格移向相邻的网格,即从坐标为(i,j)的网格移向(i-1, j),(i+1, j),(i,j-1),(i,j+1)四个网格,机器人不能走出整个n*n的网格。游戏开始时,你可以自由选定机器人的初始位置。现在你知道在一段时间内,鼹鼠出现的时间和地点,希望你编写一个程序使机器人在这一段时间内打死尽可能多的鼹鼠。

    Input

    第一行为n(n<=1000), m(m<=10000),其中m表示在这一段时间内出现的鼹鼠的个数,接下来的m行每行有三个数据time,x,y表示有一只鼹鼠在游戏开始后time个时刻,在第x行第y个网格里出现了一只鼹鼠。Time按递增的顺序给出。注意同一时刻可能出现多只鼹鼠,但同一时刻同一地点只可能出现一只鼹鼠。

    Output

    仅包含一个正整数,表示被打死鼹鼠的最大数目

    Sample Input

    2 2
    1 1 1
    2 2 2

    Sample Output

    1

    HINT

    给了10s,感觉可能有点给的多了,但是好像第一次A用了4s多一点,看到BZOJ上有人用了几十MS就A,感觉好厉害,希望他们不是打表就好……
    做法应该和最长上升子序列差不多,只是好像不能用最长上升子序列的那个log的做法,因为无法判定哪个状态最佳……
     
    第一种做法
     
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    
    int f[100000],t[100000],x[100000],y[100000];
    
    int abs(int a)
    {
        if(a<0)return -a;
        else return a;
    }
    
    bool check(int i,int j)
    {
        if((abs(x[j]-x[i])+abs(y[j]-y[i]))<=abs(t[j]-t[i]))
            return true;
        else return false;
    }
    
    int main()
    {
        int n,m,ans=1;
        fill(f+1,f+15000+1,1);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d%d",&t[i],&x[i],&y[i]);
            for(int j=1;j<i;++j)
                if(check(i,j))
                    f[i]=max(f[i],f[j]+1);
            ans=max(f[i],ans);
        }
        printf("%d",ans);
    }

    就是一维数组记录在打第i只地鼠时所能打死的最多地鼠的数量

    然后用i之前的至来更新他

    好像二重循环比较慢的样子,需要m^2 ,但是好像是能优化掉一个m的,到log级别

    只是看黄学长的优化方法,好像有点懵

    做这个题有一点需要格外注意, f 数组一开始要初始化为 1 ,因为一开始的那只地鼠是肯定能打掉的……

    第二种做法

    是黄学长的优化,看起来好像与m^2做法没什么不同,但是好像结果很出人意料

    #include<iostream>
    #include<cstdio>
    #define maxn 10005
    using namespace std;
    
    int m,n;
    int fx[maxn],x[maxn],y[maxn],t[maxn],f[maxn];
    
    int abs(int a)
    {
        if(a<0)return -a;
        else return a;
    }
    
    bool judge(int i,int j)
    {
        if((abs(x[j]-x[i])+abs(y[j]-y[i]))<=abs(t[j]-t[i]))
            return true;
        else return false;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        int ans=1;
        fx[1]=1;
        for(int i=1;i<=m;++i)
        {
            f[i]=true;
            scanf("%d%d%d",&t[i],&x[i],&y[i]);
            for(int j=i-1;j>=1;--j)
            {
                if(fx[j]<f[i])break;
                if(f[j]<f[i])continue;
                if(judge(i,j))f[i]=f[j]+1;
            }
            fx[i]=max(fx[i-1],f[i]);
            ans=max(ans,f[i]);
        }
        printf("%d",ans);
        return 0;
    }

    仿佛变了魔术……从4754MS优化到60MS,我只是稍微写了个优化而已……

    就是加了个数组记录最优解而已,然后在不可能的情形下退出循环而已……

    竟然快了这么多……

    这个题启示我们优化一定要好好学……

    这可能也是我这几天见过的最简单的BZOJ的题了吧,竟然能水过去……

  • 相关阅读:
    LeetCode 第三大的数414. Third Maximum Number
    ltp工具使用配置
    eclipse 导入项目时候java版本不一致问题
    GitHub上传不了的解决 ssh: connect to host github.com port 22: Bad file number git did not exit cleanly (exit code 128)
    Python文件中文编码问题
    图算法习题
    VMware连不上网解决
    自定义结构或类的比较
    贪心算法
    编写Lex和Yacc
  • 原文地址:https://www.cnblogs.com/qdscwyy/p/6856711.html
Copyright © 2011-2022 走看看