鞍山 中企动力提供网站建设,网站开发甲方需求文档,网站收录入口申请,麻将软件开发平台正题
题目链接:http://poj.org/problem?id1821 题目大意
有n个木板,m个工人#xff0c;每个木板只能被粉刷一次#xff0c;第i个工人如果刷的话必须刷木板SiSi#xff0c;连续的不超过LiLi的#xff0c;没一块PiPi。 解题思路
用fi,jfi,j表示前j块木板#xff0c;前i个…正题
题目链接:http://poj.org/problem?id1821 题目大意
有n个木板,m个工人每个木板只能被粉刷一次第i个工人如果刷的话必须刷木板SiSiS_i连续的不超过LiLiL_i的没一块PiPiP_i。 解题思路
用fi,jfi,jf_{i,j}表示前j块木板前i个工人最大价值然后如果什么都不做就是fi−1,jfi−1,jf_{i-1,j}也可以空着不刷fi,j−1fi,j−1f_{i,j-1}。然后我们就在1∼Li1∼Li1\sim L_i的范围内找到
fi,jmaxj−Li≤k≤Si−1{fi−1,jPi∗(j−k)}(j≥Si)fi,jmaxj−Li≤k≤Si−1{fi−1,jPi∗(j−k)}(j≥Si)
f_{i,j}=\max_{j-L_i\leq k \leq S_i-1}\{f_{i-1,j}+P_i*(j-k)\}(j\geq S_i) 然后用单调队列维护k就好了。code
#includecstdio
#includequeue
#includealgorithm
using namespace std;
struct node{int l,p,s;
}a[110];
int n,m,f[110][16010];
dequeint q;
bool cmp(node x,node y)
{return x.sy.s;}
int calc(int i,int k){return f[i-1][k]-a[i].p*k;
}
int main()
{scanf(%d%d,n,m);for(int i1;im;i)scanf(%d%d%d,a[i].l,a[i].p,a[i].s);sort(a1,am1,cmp);for(int i1;im;i){while(!q.empty())q.pop_back();for(int kmax(0,a[i].s-a[i].l);ka[i].s-1;k){while(!q.empty()calc(i,q.back())calc(i,k)) q.pop_back();q.push_back(k);}//加入元素for(int j1;jn;j){f[i][j]max(f[i-1][j],f[i][j-1]);//啥都不干if(ja[i].s){while(!q.empty()q.front()j-a[i].l) q.pop_front();//维护区域if(!q.empty()) f[i][j]max(f[i][j],calc(i,q.front())a[i].p*j);//统计答案}}}printf(%d,f[m][n]);
}