这题刚开始想练一练单调队列优化DP,但由于本人太菜,实在是搞不定,就换了个思路来写这道题。

把所有有power的点排序,然后遍历点,对于每个点,枚举前面的能到这个点的点,从中取最大的就🆗

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;

struct node
{
    int x,y,z;
}t[5010];

int n,m,k,ti;
int f[5010],ans;

bool cmp(node k,node l)
{
    return k.x < l.x;
}

int main()
{
    scanf("%d%d%d%d",&n,&m,&k,&ti);
    for(int i = 0;i < k; ++i)
        scanf("%d%d%d",&t[i].x,&t[i].y,&t[i].z);
    sort(t,t + k,cmp);
    ans = 0;
    memset(f,0,sizeof(f));
    for(int i = 0;i < k; ++i)
    {
        f[i] = t[i].z;
        for(int j = 0;j < i; ++j)
        {
            if(abs(t[i].y - t[j].y) <= ti * abs(t[i].x - t[j].x))
                f[i] = max(f[i],f[j] + t[i].z);
        }
        ans = max(ans,f[i]);
    }
    printf("%d\n",ans);
    return 0;
}

 

后来做了一下洛谷P1886,稍微懂了一丢丢,也贴一个代码吧(纪念自己在这个题上WA了这么多次)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;

int n,k,tot,x;
int l,r,q[1000100],a[1000100];
int ans[1000100];

int main()
{
    scanf("%d%d",&n,&k);
    tot = 0;
    l = 1; r = 1;
    for(int i = 1;i <= n; ++i) scanf("%d",&a[i]);
    q[1] = a[1];
    for(int i = 1;i <= n; ++i)
    {
        while(l <= r && q[r] >= a[i] && r) r--;
        q[++r] = a[i];
        if(i >= k)
        {
            if(a[i - k] == q[l]) l++;
             ans[++tot] = q[l];
        }
    }
    for(int i = 1;i <= tot; ++i)
    {
        printf("%d",ans[i]);
        if(i != tot) printf(" ");
            else printf("\n");
    }
    tot = 0;
    memset(q,0,sizeof(q));
    l = 1; r = 1;
    q[1] = a[1];
    for(int i = 1;i <= n; ++i)
    {
        while(l <= r && q[r] <= a[i]) r--;
        q[++r] = a[i];
        if(i >= k)
        {
            if(a[i - k] == q[l]) l++;
            ans[++tot] = q[l];
        }

    }
    for(int i = 1;i <= tot; ++i)
    {
        printf("%d",ans[i]);
        if(i != tot) printf(" ");
            else printf("\n");
    }
    return 0;
}

其实刚开始想的是N*M*T肯定TLE,就套用单调队列优化DP的式子看了一下觉得可以用这个省掉T那一维,但是理解不深实在考虑不出如何实现,,,做完1886这个题好像稍微懂一点了,ennnn 趁热打铁,我再去看看这个题

哈哈,我又回来了,终于看懂了,不容易啊。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;

int n,m,k,t,x,y,ans;
int l,r;
int a[5010][5010];
int q[5010][2];   //q[][0]存储数据,q[][1]存储位置用以判断是否在符合条件的区间
int dp[5010][5010];

int main()
{
    scanf("%d%d%d%d",&n,&m,&k,&t);
    for(int i = 1;i <= k; ++i)
    {
        scanf("%d%d",&x,&y);
        scanf("%d",&a[x][y]);
    }
    for(int i = 1;i <= n; ++i)
    {
        l = 1; r = 0;
        for(int j = 1;j <= min(m,t); ++j)  
        {
            while(l <= r && q[r][0] <= dp[i - 1][j]) r--;
            q[++r][0] = dp[i - 1][j];
            q[r][1] = j;
        }
        for(int j = 1;j <= m; ++j)
        {
            if(j + t <= m)  
            {
                while(l <= r && q[r][0] <= dp[i - 1][j + t]) r--;
                q[++r][0] = dp[i - 1][j + t];
                q[r][1] = j + t;
            }
            if(q[l][1] < j - t) l++;   //判断是否在符合条件的区间
            dp[i][j] = q[l][0] + a[i][j];
        }
    }
    ans = 0;
    for(int i = 1;i <= m; ++i) ans = max(ans,dp[n][i]);
    printf("%d\n",ans);
    return 0;
}