思路:每次枚举每个工人的右边界j,维护最优的左边界k。那么dp[j]=max(dp[j],dp[k]+(j-k)*w[i].p);
对于每个工人的初值k=w[i].s-1;
令x=j-w[i].l,如果(k-x)*w[i].p>dp[k]-dp[x],则k=x。
#include<set> #include<map> #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<string> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define pb push_back #define mp make_pair #define Maxn 170010 #define Maxm 200010 #define LL __int64 #define Abs(x) ((x)>0?(x):(-x)) #define lson(x) (x<<1) #define rson(x) (x<<1|1) #define inf 100000 #define lowbit(x) (x&(-x)) #define clr(x,y) memset(x,y,sizeof(x)) #define Mod 1000000007 using namespace std; int dp[Maxn]; struct Workers{ int s,p,l; int operator<(const Workers &temp) const{ return s<temp.s; } }w[110]; int main() { int n,i,j,K,k,x; //freopen("aa.txt","r",stdin); while(scanf("%d%d",&n,&K)!=EOF){ clr(dp,0); for(i=1;i<=K;i++){ scanf("%d%d%d",&w[i].l,&w[i].p,&w[i].s); } sort(w+1,w+1+K); int ed,st,temp; for(i=1;i<=K;i++){ int ed=w[i].s+w[i].l-1; k=w[i].s-1; for(j=ed;j>=w[i].s;j--){ x=j-w[i].l; x=max(x,0); if((k-x)*w[i].p>dp[k]-dp[x]) k=x; dp[j]=max(dp[j],dp[k]+(j-k)*w[i].p); } for(j=1;j<=n;j++) dp[j]=max(dp[j],dp[j-1]); } printf("%d ",dp[n]); } return 0; }