[洛谷]P2285 [HNOI2004]打鼴鼠 (#線性dp)

題目描述

鼴鼠是一種很喜歡挖洞的動物,但每過一定的時間,它還是喜歡把頭探出到地面上來透透氣的。根據這個特點阿牛編寫了一個打鼴鼠的遊戲:在一個n*n的網格中,在某些時刻鼴鼠會在某一個網格探出頭來透透氣。你可以控制一個機器人來打鼴鼠,如果i時刻鼴鼠在某個網格中出現,而機器人也處於同一網格的話,那麼這個鼴鼠就會被機器人打死。而機器人每一時刻只能夠移動一格或停留在原地不動。機器人的移動是指從當前所處的網格移向相鄰的網格,即從座標爲(i,j)的網格移向(i-1, j),(i+1, j),(i,j-1),(i,j+1)四個網格,機器人不能走出整個n*n的網格。遊戲開始時,你可以自由選定機器人的初始位置。

現在知道在一段時間內,鼴鼠出現的時間和地點,請編寫一個程序使機器人在這一段時間內打死儘可能多的鼴鼠。

輸入格式

從文件input.txt中讀入數據,文件第一行爲n(n<=1000), m(m<=10000),其中m表示在這一段時間內出現的鼴鼠的個數,接下來的m行中每行有三個數據time,x,y表示有一隻鼴鼠在遊戲開始後time個時刻,在第x行第y個網格里出現了一隻鼴鼠。Time按遞增的順序給出。注意同一時刻可能出現多隻鼴鼠,但同一時刻同一地點只可能出現一隻鼴鼠。

輸出格式

輸出文件output.txt中僅包含一個正整數,表示被打死鼴鼠的最大數目。

輸入輸出樣例

輸入 #1複製

2 2	         
1 1 1		
2 2 2

輸出 #1複製

1

思路

一開始想用3維dp的,一想肯定爆。三維dp的狀態定義是令dp[i][j][k]爲機器人走到(i,j)時,消耗的時間爲k時,能打到的最多鼴鼠量是多少。

令dp[i]表示到第i只鼴鼠,最多能抓多少隻小鼠。很容易看出它能從第i個時間點前的任意一個時間點轉移來,則:

dp[i]=min(dp[i],dp[j]+1)

你有沒有發現,這不就是LIS嗎?!是的,因爲題目告訴我們時間按遞增的順序給出。

在任何時候,都至少能打死一隻鼴鼠,所以任意dp[i]=1。

此題涉及能否到達,所以在轉移前判斷曼哈頓距離是否小於時間差。

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <memory.h>
#define maxn 10001
using namespace std;
int dp[maxn],n,m,s;
struct mouse
{
	int x,y,t;
}a[maxn];
inline int dis(int x,int y)//曼哈頓距離 
{
	return abs(a[x].x-a[y].x)+abs(a[x].y-a[y].y);
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	register int i,j,k;
	cin>>n>>m;
	for(i=1;i<=m;i++)
	{
		cin>>a[i].t>>a[i].x>>a[i].y;
		dp[i]=1;
	}
	for(i=1;i<=m;i++)
	{
		for(j=1;j<i;j++)//j爲枚舉時間點 
		{
			if(dis(i,j)<=abs(a[i].t-a[j].t))
			{
				dp[i]=max(dp[i],dp[j]+1);
			}
		}
	}
	for(i=1;i<=m;i++)//掃一遍答案 
	{
		s=max(dp[i],s);
	}
	cout<<s<<endl;
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章