1. 程式人生 > 實用技巧 >HNOI 2004 打鼴鼠

HNOI 2004 打鼴鼠

HNOI 2004 打鼴鼠

洛谷傳送門

JDOJ傳送門

Description

鼴鼠是一種很喜歡挖洞的動物,但每過一定的時間,它還是喜歡把頭探出到地面上來透透氣的。根據這個特點阿牛編寫了一個打鼴鼠的遊戲:在一個nn的網格中,在某些時刻鼴鼠會在某一個網格探出頭來透透氣。你可以控制一個機器人來打鼴鼠,如果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


題解:

思路:最優化:想DP。

想狀態:第一種狀態是dp[i]表示前i個鼴鼠都被打完後的答案。但是這顯然是錯誤的。因為前i個鼴鼠不一定都要被打。第二種狀態是dp[i]表示打到第i個鼴鼠(也就是不一定前i個都被打)時,能打到的最多的鼴鼠只數。

這個貌似可以。嘗試轉移。

轉移:判斷是否能在時限內從當前位置挪到另外的位置,就是橫縱座標差絕對值的和(Manhaton曼哈頓距離)和時間差做比較,如果可以跑到這個位置,就能轉移。

轉移方程當然很好想:

\[dp[i]=\max(dp[i],dp[j]+1) \]

答案是所有dp[i]的最大值。

程式碼:

#include<cstdio>
#include<cmath>
#include<algorithm>
#define R register
using namespace std;
const int maxn=10010;
int n,m,ans;
int t[maxn],x[maxn],y[maxn],dp[maxn];
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
inline int read()
{
    int x=0,f=1;
    char ch=nc();
    while(ch<48||ch>57)
    {
        if(ch=='-')
            f=-1;
        ch=nc();
    }
    while(ch>=48&&ch<=57)
        x=x*10+ch-48,ch=nc();
   	return x*f;
}
int main()
{
    n=read();m=read();
    for(R int i=1;i<=m;i++)
    {
        t[i]=read();x[i]=read();y[i]=read();
        dp[i]=1;
    }
    for(R int i=1;i<=m;i++)
        for(R int j=1;j<i;j++)
            if(abs(x[i]-x[j])+abs(y[i]-y[j])<=abs(t[i]-t[j]))
                dp[i]=max(dp[i],dp[j]+1);
    for(R int i=1;i<=m;i++)
        ans=max(ans,dp[i]);
    printf("%d",ans);
    return 0;
}