poj1014 diving 原来是这样T_T


    这题wa了一天才ac.......囧

====================================================================

   首先主算法是dp无疑,用2进制处理成01背包,貌似还要加上滚动优化,虽然我不懂100*60000的喂马会爆.

 wa点1:2进制优化

 从上次月赛接触了2进制优化,而到现在我才真正理解.

 2进制优化是:假如本来有x个同种物品,可决策的物品数就是x.而2进制处理过后就变成1*val,2*val,4*val.......多种可以同时取的物品,只有lgx个物品了,规模大大减小

   例如:取3个就相当于取了val和2*val的物品只有2次决策......按原来的方法有3次决策.

 错误的写法:

View Code
scanf("%d%d",&x,&val);
while(x)
{
w[k++]=x*;
x/=2;
}

 

如果某种物品有x个  被处理成价值为x*val, (x/2)*val......的物品,假设容量很大,能全部取走,就相当于取了x+x/2+.......

显然大于原有的物品数,这是个明显的错误T_T......当时我居然忽略了.

 正确的写法:

 

View Code
scanf("%d%d",&x,&val)int t;t=1;
while(x-t>0)
{
w[k++]=t*val;
x-=t;
t*=2;
}
w[k++]=x*val;


 

 wa点2:

 滚动优化

 滚动优化要倒序.....要倒叙要倒序要倒序要倒序........今天第一次注意到,我不知道以前用滚动优化的题目是怎么ac的,测试数据太弱了吧......要不是这道wa还一直不知道

 后怕...后怕...后怕

 喂马要倒序呢?网上没有搜到权威的说法,写下自己的想法:

 先看朴素的dp

View Code
for(i=0;i<n;i++)
for(j=w[i];j<m;j++)
{
f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+w[i]);
}


滚动优化后如果第2层循环是

 for(j=w[i];j<m;j++)

 f[j]=max(f[j],f[j-w[i]]+w[i]);

 这样j点被f[j-w[i]]更新后,还会继续更新点j+w[i],但是此时的j与j+w[i]应该是同一层的即f(i,)层的,这样dp的阶段就混乱不堪了.

 再看倒序后的

 for(j=m-1;j>=w[i];j--)

 f[j]=max(f[j],f[j-w[i]]+w[i]);

 j点被j-w[i]更新, j-w[i]被比它更小的更新...... 该层的每个点都只被上层的更新过,阶段还是很清晰的......

 

 另外个人觉得直接用dp[2][size]应该也行,dp[0][]存上一阶段的,dp[1][]存当前的,下标t用 t=(t+1)%2轮换就行了......

 尝试如此改进,提交后wa一次,不知是不是别的原因.

你可能感兴趣的:(div)