题意:a,b两个属性,每天可以+1点a,或者+1点b,然后当a>xi并且b>yi,可以获得zi的奖励,之后的每天都可以获得zi的奖励,现在来求zi最大是多少
题解:离散化dp
我们先假设xi和yi,m比较小,那么先求v[i][j],表示在a=i,b=j时在剩下的天数里即(m-i-j)天里每天可以获得的zi值
也就是
图片说明
图片说明
相当于求的是从第一天起,到a加了i点,b加了j点,时可以获得的全部的zi值
那么对于最后答案就是
图片说明
图片说明
即,求a=i和b=j时状态,可以由两个状态得到,即i-1,j和i,j-1状态,然后这两个状态取最大加上v[i][j],就是到a=i,b=j时的所获得的zi值
然后因为有m天,所以要再求下ans
时间复杂度:图片说明
然后还没完,刚一半
这个题给的m,xi,yi都比较大,然后下来用到离散化

离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。例如:
原数据:1,999,100000,15;处理后:1,3,4,2;
原数据:{100,200},{20,50000},{1,400};
处理后:{3,4},{2,6},{1,5};---来自百度百科

然后对于离散的方法就是,排序,去重
sort和unique
先通过记录下每个数字,然后对其进行排序和去重,一定要先排序
排序之后的数字所对应的下标,就是我们的新的i和j

 for(int i=1;i<=n;i++){ 
        scanf("%d%d%d",&x,&y,&z);
        if(x+y>m)continue;
        p[++cnt].x=x;
        p[cnt].y=y;
        p[cnt].z=z;
        X[++cnt1]=x;
        Y[++cnt2]=y;
    }
    sort(X+1,X+1+cnt1); 
    cnt1=unique(X+1,X+1+cnt1)-X-1;
    sort(Y+1,Y+1+cnt2);
    cnt2=unique(Y+1,Y+1+cnt2)-Y-1;
    for(int i = 1; i <= n; i++) {
        int cn = lower_bound(X+1,X+1+cnt1,p[i].x) -X;
        int cy = lower_bound(Y+1,Y+1+cnt2,p[i].y) -Y;
        v[cn][cy] +=p[i].z;
    }

以上操作就相当于把很大的数字转化为较小的数字,也就是数组可以开的下的大小,和运算次数可以过的数量级
那么到此就把数字比较大的问题解决,所以就会到上面的状态转移式子
总结就是那一个数组的下标来代替一个比较大的数字
但是到此出现问题就是求a=i和b=j时,可以由两个状态得到,即i-1,j和i,j-1状态,上面的数字比较小的话那么i和i-1的差值为1,那么就不存在这个问题,但是现在的问题就是i和i-1的状态的差值不为1,状态之间相差图片说明
所以dp转移式子变成
图片说明
状态转移相差的天数要加上相应的v[i][j]
然后ans的也发生相应的变化
图片说明
离散化相当与预处理:
时间复杂度为:图片说明
然后对于离散化的题的时间复杂度都是假的..........具体要看离散化的程度,以上时间复杂度仅供参考

#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
#define maxx 1005
using namespace std;
struct  node
{
    int x,y,z;
}p[maxx]; 
long long  X[maxx]; 
long long  Y[maxx];
long long v[maxx][maxx]; 
long long dp[maxx][maxx]; 
int cnt1,cnt2,cnt; 
int main()
{
    int n,m;
    cin>>n>>m;
    int x,y,z;
    for(int i=1;i<=n;i++){ 
        scanf("%d%d%d",&x,&y,&z);
        if(x+y>m)continue;
        p[++cnt].x=x;
        p[cnt].y=y;
        p[cnt].z=z;
        X[++cnt1]=x;
        Y[++cnt2]=y;
    }
    sort(X+1,X+1+cnt1); 
    cnt1=unique(X+1,X+1+cnt1)-X-1;
    sort(Y+1,Y+1+cnt2);
    cnt2=unique(Y+1,Y+1+cnt2)-Y-1;
    for(int i = 1; i <= n; i++) {
        int cn = lower_bound(X+1,X+1+cnt1,p[i].x) -X;
        int cy = lower_bound(Y+1,Y+1+cnt2,p[i].y) -Y;
        v[cn][cy] +=p[i].z;
    }
    for(int i=1;i<=cnt1;i++)
    for(int j=1;j<=cnt2;j++)
        v[i][j]+=v[i-1][j]+v[i][j-1]-v[i-1][j-1];
    for(int i=1;i<=cnt1;i++)
    for(int j=1;j<=cnt2;j++)
        dp[i][j]=v[i][j]+max(dp[i-1][j]+(X[i]-X[i-1]-1)*v[i-1][j],dp[i][j-1]+(Y[j]-Y[j-1]-1)*v[i][j-1]);
    long long ans=0;
    for(int i=1;i<=cnt1;i++)
    for(int j=1;j<=cnt2;j++)
        if(X[i]+Y[j]<=m)ans=max(ans,dp[i][j]+(m-X[i]-Y[j])*v[i][j]);

    cout<<ans<<endl;
    return 0;
}