zoukankan      html  css  js  c++  java
  • BZOJ 1207 [HNOI2004]打鼹鼠:dp【类似最长上升子序列】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1207

    题意:

      有一个n*n的网格,接下来一段时间内会有m只鼹鼠出现。

      第i只鼹鼠会在tim[i]秒出现,位置为(x[i],y[i])。数据保证tim[i]递增给出。

      你有一个打鼹鼠的机器,初始位置可以自定。机器每秒钟只能原地不动或者走一格。在某一秒机器位置与鼹鼠出现的位置相同时,认为这个鼹鼠被打到。

      问你最多能打多少鼹鼠。

    题解:

      乍一看和HDU 1176 免费馅饼很像:

        dp[i][x][y] = 第i秒在(x,y)最多打的鼹鼠数

      但是时间和空间都会爆。。。

      for循环时间:O(n^4 * m)

      改为记忆化搜索:O(n^2 * m^2)

      (时间 = 枚举起始位置 * 求dp)

      打鼹鼠有一个和最长上升子序列相似的性质:

        打鼹鼠:如果tim[i] < tim[j],那么鼹鼠j只可能在鼹鼠i出现之后打。

        LIS:如果i < j,那么s[j]只可能在考虑完s[i]之后加入答案。

      表示状态:

        dp[i] = max hit

        i:打了第i只鼹鼠

      找出答案:

        max dp[i]

      如何转移:

        dp[i] = max dp[j] + 1 (j < i, tim[i]-tim[j] >= manhattan(ci,cj))

        (j在i之前,并且可以在限定时间内从j到达i(曼哈顿距离)

      边界条件:

        set dp = 1

        至少打了自己。

    AC Code:

     1 // state expression:
     2 // dp[i] = max hit
     3 // i: ith mole is dead
     4 //
     5 // find the answer:
     6 // max dp[i]
     7 //
     8 // transferring:
     9 // dp[i] = max dp[j] + 1 (tim[i]-tim[j] >= manhattan(ci,cj))
    10 //
    11 // boundary:
    12 // set dp = 1
    13 #include <iostream>
    14 #include <stdio.h>
    15 #include <string.h>
    16 #include <stdlib.h>
    17 #define MAX_M 10005
    18 
    19 using namespace std;
    20 
    21 int n,m;
    22 int ans=0;
    23 int x[MAX_M];
    24 int y[MAX_M];
    25 int tim[MAX_M];
    26 int dp[MAX_M];
    27 
    28 void read()
    29 {
    30     cin>>n>>m;
    31     for(int i=0;i<m;i++)
    32     {
    33         cin>>tim[i]>>x[i]>>y[i];
    34     }
    35 }
    36 
    37 void solve()
    38 {
    39     for(int i=0;i<m;i++)
    40     {
    41         dp[i]=1;
    42         for(int j=0;j<i;j++)
    43         {
    44             if(tim[i]-tim[j]>=abs(x[i]-x[j])+abs(y[i]-y[j]))
    45             {
    46                 dp[i]=max(dp[i],dp[j]+1);
    47             }
    48         }
    49         ans=max(ans,dp[i]);
    50     }
    51 }
    52 
    53 void print()
    54 {
    55     cout<<ans<<endl;
    56 }
    57 
    58 int main()
    59 {
    60     read();
    61     solve();
    62     print();
    63 }
  • 相关阅读:
    matlab 自定义函数及调用
    matlab 逻辑数组及其应用
    matlab 嵌套循环的学习
    matlab和C语言的break及continue测试
    matlab 向量法建数组(推荐)
    matlab for循环应用(阶乘及the day of year)
    matlab for循环的三种类型
    ORACLE创建用户,建表空间,授予权限
    Linux计划任务
    android开发环境搭建
  • 原文地址:https://www.cnblogs.com/Leohh/p/7504974.html
Copyright © 2011-2022 走看看