标签:-- 过程 can 就是 problem clu amp std 上下
题意:给长度为n的木板,k个工人,每个工人要么不粉刷,或者选择一个包含木板si,长度不超过li的连续的一段木板粉刷,每粉刷一块得到pi的报酬,问如何安排工人使得总报酬最大?
思路:可以按si给工人排序,这样我们就可以按照顺序依次安排工人。设f[i][j]表示到第i个工人,刷到前j块木板的最大报酬,
三种情况
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=16005;
struct note
{
int l,p,s;
} a[maxn];
int q[maxn];
bool operator <(note a,note b)
{
return a.s<b.s;
}
int f[105][maxn];
int calc(int i,int k)
{
return f[i-1][k]-a[i].p*k;
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1; i<=k; i++)
scanf("%d%d%d",&a[i].l,&a[i].p,&a[i].s);
sort(a+1,a+1+k);
for(int i=1; i<=k; i++)
{
int l=1,r=0;
for(int k=max(0,a[i].s-a[i].l);k<=a[i].s-1;k++)
{
while(l<=r&&calc(i,q[r])<=calc(i,k)) r--;
q[++r]=k;
}
for(int j=1; j<=n; j++)
{
f[i][j]=max(f[i-1][j],f[i][j-1]);
if(j>=a[i].s)
{
while(l<=r&&q[l]<j-a[i].l) l++;
if(l<=r) f[i][j]=max(f[i][j],calc(i,q[l])+a[i].p*j);
}
}
}
printf("%d\n",f[k][n]);
}
标签:-- 过程 can 就是 problem clu amp std 上下
原文地址:https://www.cnblogs.com/dongdong25800/p/11408922.html