The Hard Work of Paparazzi(dp巧妙优化)
链接
题意:r,n代表一个r * r的矩阵,n代表有n个金币,初始时间是0,现在你站在(1,1)位置,然后给出n个金币出现的位置(x,y)和出现的时间t,这个金币只在t这一分钟出现,过了t就消失,然后保证给出的t是严格递增的,求你能获得的最大收益。每分钟你能向四周移动一个单位。
思路:dp[i]以第i个结尾的最大值,只想到on^2的做法,但后来发现因为r很小,t又是递增的,第二层循环只要枚举(i-4r~i-1)就行了,为什么呢,因为i-5r一定能更新i-3*r,那么如果枚举所有点,这样就多余了。复杂度O(nr)
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int dp[N];
int r,n;
struct node{
int t;
int x;
int y;
}q[N];
int mx[N];
int main()
{
cin >> r >> n;
for(int i=1;i<=n;i++)
{
int t,x,y;
cin>>t>>x>>y;
//x+=y;
q[i]={
t,x,y};
}
q[0]={
0,1,1};
memset(dp,-0x3f,sizeof dp);
dp[0]=0;
// for(int i=1;i<=n;i++)
// {
// //dp[i]=1;
// for(int j=i-1;j>=0;j--)
// {
// if(q[j].t+abs(q[i].x-q[j].x)+abs(q[i].y-q[j].y)<=q[i].t)
// dp[i]=max(dp[i],dp[j]+1);
// if(dp[i]==mx[j]+1)
// break;
// }
// mx[i]=max(mx[i-1],dp[i]);
// }
for(int i=1;i<=n;i++)
{
//dp[i]=1;
for(int j=i-1;j>=max(0,i-2*r-1);j--)
{
if(q[j].t+abs(q[i].x-q[j].x)+abs(q[i].y-q[j].y)<=q[i].t)
dp[i]=max(dp[i],dp[j]+1);
if(dp[i]==mx[j]+1)
break;
}
mx[i]=max(mx[i-1],dp[i]);
}
int res=0;
for(int i=1;i<=n;i++)
res=max(res,dp[i]);
cout<<res<<endl;
return 0;
}