您的位置:首页 > 其它

hdu 2191 单调队列优化

2012-07-24 17:05 218 查看
F[i][j] = max { F[i - 1] [j – k * v[i] ] + k * w[i] } (0 <= k <= m[i]) 是朴素的多重背包的转移公式

假设 v[i]为容量 w[i]为价值 no[i]为数量

a = j / v[i] 即a为i种物品最大可能使用次数。 b = j % v[i] 即不能用i种物品表达的价值。

则朴素转移公式可化为: F[i][j] = max { F[a*v[i] + b - k*v[i] ] + (a-k)*w[i] }

用 k 代替 a - k 得 F[i][j] = max { F[i-1][ k * v[i] + b] - k*[w] } + a*w[i] 其中 (k : 0 --> j /a)

单调队列就是用来算F[i][j] - a*w[i] 的最值的。

hdu 2191的 代码:

#include<iostream>
#include<string.h>
using namespace std;
typedef struct
{
int x,t;
}Q;
int f[110];
int v[110],w[110],no[110];
Q ux[110];
int n,m;
int fabs(int x)
{
if(x<0) return -x;
return x;
}
int main()
{
int ti;
int s,t;
scanf("%d",&ti);
while(ti--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)  scanf("%d%d%d",&v[i],&w[i],&no[i]);
memset(f,0,sizeof(f));
for(int i=0;i<m;i++)
{
for(int j=0;j<v[i];j++) //使用当前i种物品时,不可能达到的情况,j=0~~n/v[i]
{
s=0; t=-1;
for(int k=0;k<=(n-j)/v[i];k++)//当前i种物品可能使用次数
{
int temp=f[j+k*v[i]]-k*w[i];//一下求max{f[(a-k)v+b}-(a-k)v即f[kv+j]-kv}
while(ux[t].x<temp&&s<=t) t--;
ux[++t].x=temp; ux[t].t=k;
while(fabs(ux[t].t-ux[s].t)>no[i]&&s<=t) s++;
f[j+k*v[i]]=ux[s].x+k*w[i];
}
}
}
printf("%d\n",f
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: