1. 程式人生 > >BZOJ 1207(dp)

BZOJ 1207(dp)

傳送門

題面:

1207: [HNOI2004]打鼴鼠

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 4197  Solved: 2019
[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

題目分析:

    最開始以為是個簡單的搜尋,但是寫著寫著發現有些不對,題目中要求的是最開始的機器人的放置位置是任意的。這樣的話爆搜的話會比較困難。

    實際上是一個挺巧妙的dp。我們考慮每一個玩具對答案的貢獻,設dp[i]為打了第i個地鼠的前提下,最大可以打的地鼠的個數。此後,我們分別列舉兩個地鼠的座標。此時,倘若第i個地鼠與第j個地鼠的曼哈頓距離不大於他們之間的時間差,則代表著此時能夠對第j個地鼠進行打擊,即此時 有轉移,我們不斷維護這樣的最大值即可。時間複雜度O(m^2)

程式碼:

#include <bits/stdc++.h>
#define maxn 10005
using namespace std;
int dp[maxn];
struct Node{
int x,y,time;
}q[maxn];
int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        dp[i]=1;
        scanf("%d%d%d",&q[i].time,&q[i].x,&q[i].y);
    }
    for(int i=1;i<=m;i++){
        for(int j=1;j<i;j++){
            if(abs(q[i].x-q[j].x)+abs(q[i].y-q[j].y)<=q[i].time-q[j].time){
                dp[i]=max(dp[i],dp[j]+1);
            }
        }
    }
    int maxx=0;
    for(int i=1;i<=m;i++) maxx=max(maxx,dp[i]);
    cout<<maxx<<endl;
    return 0;
}