题目描述
可以把游戏界面理解成一个N行M列的棋盘,有K个格子上有P点,其价值为val(i,j)
初始灵梦可以选择在第一行的任意一个格子出发,每秒她必须下移一格。
灵梦具有一个左右移动的速度T,可以使她每秒向左或右移动至多T格,也可以不移动,并且不能折返。移动可视为瞬间完成,不经过路途上的点,只能获得目标格子的P点。
求最终她能获得的POWER值最大是多少?
输入格式:
第一行四个数字,N,M,K,T
接下来K行每行3个数字x,y,v,代表第x行第y列有一个val为v的P点,数据保证一个格子上最多只有1个P点。
输出格式:
一个数字
说明
对于40%的测试点,1<=N,M,T,K<=200
对于100%的测试点,1<=N,M,T,K<=4000
v<=100,N,M,K,T均为整数
题目分析
可能很多人第一眼看过去都以为用dp[i][j]表示走到第i行第j列三层循环就能过.
如果你第一眼不是这么想当我没说.
反正我是这样爆T六个点.
这题的突破口就在于不是每个点都有权值
所以我们只用记录那些有权值的点
然后用那些能到达当前节点的点更新当前结点最大值就好了
具体来说就是先将结点按x坐标升序排序
若
a
b
s
(
x
i
−
x
j
)
∗
T
>
=
a
b
s
(
y
i
−
y
j
)
abs(x_i-x_j)*T>=abs(y_i-y_j)
abs(xi−xj)∗T>=abs(yi−yj)
就更新
d
p
[
i
]
=
m
a
x
(
d
p
[
i
]
,
m
a
x
(
d
p
[
i
]
,
d
p
[
j
]
+
v
a
l
i
)
dp[i]=max(dp[i],max(dp[i],dp[j]+val_i)
dp[i]=max(dp[i],max(dp[i],dp[j]+vali)
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
int n,m,k,t;
struct node{int x,y,val;}a[5010];
int dp[5010];
int ans=-1e9;
bool cmp(node a,node b){return a.x<b.x;}
int main()
{
n=read();m=read();k=read();t=read();
for(int i=1;i<=k;++i)
a[i].x=read(),a[i].y=read(),a[i].val=read();
sort(a+1,a+1+k,cmp);
dp[1]=a[1].val;
for(int i=1;i<=k;++i)
{
for(int j=0;j<i;++j)
{
if( abs(a[i].x-a[j].x)*t >= abs(a[i].y-a[j].y) )
dp[i]=max(dp[i],dp[j]+a[i].val);
}
ans=max(ans,dp[i]);
}
cout<<ans;
return 0;
}