Rexdf

The devil is in the Details.

POJ1014: 多重背包 + 二进制优化 + 取模优化

| Comments

问题描述: 有若干价值为分别为1,2 ,3,4,5,6的大理石,求总价值的均分策略。设价值为V的石头重量为V,这批石头的总价值为SUM,则问题转化为选取若干大理石将容量为SUM/2的背包装满。 背包问题(参考“背包问题9讲”) 有N件物品和一个容量为V的背包,第i件物品的费用是c[i],价值是w[i]。 f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值,则有: 0-1背包

状态转移方程 f[i][v] = max{f[i-1][v], f[i-1][v-c[i]]+w[i]}

解法 O(VN) for i = 1…N for v = V…c[i] f[v] = max{f[v], f[v-c[i]]+w[i]};

子过程 procedure ZeroOnePack(cost, weight) for v = V…cost f[v] = max{f[v], f[v-cost]+weight}

初始化 要求恰好装满背包: f[0] = 0, f[1…V] = –1 只要求价值最大: f[0…V] = 0

完全背包

状态转移方程 O(VΣ(V/c[i])) f[i][v] = max{f[i-1][v-kc[i]]+kw[i]|0<=kc[i]<=v}

转化为0-1背包问题 O(VN) for i = 1…N for v = cost…V f[v] = max{f[v], f[v-cost]+weight}

子过程 procedure CompletePack(cost, weight) for v = cost…V f[v] = max{f[v], f[v-cost]+weight}

多重背包 (指定每件物品的个数n[i])

状态转移方程 O(VΣn[i]) f[i][v] = max{f[i-1][v-kc[i]]+k*w[i]|0<=k<=n[i]}

二进制优化 O(V*Σlog(n[i])) 将第i种物品以2的指数分堆:1,2,4,…,2^(k-1),n[i]-2^k+1,且 k是满足n[i]-2^k+1>0的最大整数。每次处理一堆而不是一个物品。

伪代码 procedure MultiplePack(cost, weight, amount) if costamount>=V CompletePack(cost, weight) return integer k=1 while k<amount ZeroOnePack(kcost, kweight) amount = amount – k k = k * 2 ZeroOnePack(amountcost, amount*weight)

取模优化 当输入样本特别大时,比如给出上百万件物品,这时候仅靠优化算法仍然不能使运行时间降到满意的范围。可考虑如何减少输入样本。poj1014的discussion上有一个非常巧妙的“取模优化”法。 设价值为v(1<=v<=6)的物品共有n件,我们希望找到一个比较小的数s(s<n), 且将n件物品v减少到s或s-1件,问题的可分性不变。考虑不可分和可分两种情况:

  • 如果该问题不可分,那么n-2件v仍然不可分,依次类推,用s或 s-1替换n仍然不可分
  • 如果该问题可分,即可分成价值相等的两堆。分两种情况考虑:
  • 如果两堆里都有v。 两堆各减一个v,即n改为n-2,仍然可分,可以反复减2直至只有一堆有v。
  • 如果仅有一堆有v。 如果将n改为n-2仍可分,则必须满足两个条件: I.没有v的那一堆中,至少有一种其它物品可替换v。II.替换后两堆都至少有一个v。如果n>s时始终满足这两个条件,我们就可以用s或s-1替换n. 下面依次考虑v=1,2,3,4,5,6时如何根据“抽屉原理”得到满足条件I和II的s。 v=1时,s=6 替换法: if(n>6) n=6-n%2 1总能被其它价值替换,所以满足条件I不是问题,为满足条件2,s必须大于6。 因为6是其它价值物品中一次可替换最多1的物品。 v=2时,s=5 替换法: if(n>5) n=4+n%2 由1(2-1)+3(2-1)+4(1-1)+5(2-1)+6(1-1) = 9 < 25知,s=4时满足条件I。但这里要注意,如果另一堆可替换2的是两个5,那么一次就可替换5个2。为满足条件 II,s不能小于5。所以这里s是5而不是4。 v=3时,s=8 替换法: if(n>8) n=8-n%2 由1(3-1)+2(3-1)+4(3-1)+5(3-1)+6(1-1) = 24 < 39知,s=8时满足条件I,且最多可替换5个3,所以s=8>5也满足条件II。 v=4时,s=8 替换法: if(n>8) n=8-n%2 由1(4-1)+2(2-1)+3(4-1)+5(4-1)+6(2-1) = 35 < 49知, s=8时满足条件I,且最多可替换5个4,所以s=8>5也满足条件II。 v=5时,s=12 替换法: if(n>12) n=12-n%2 由1(5-1)+2(5-1)+3(5-1)+4(5-1)+6(5-1) = 64 < 513知,s=12满足条件I,且最多可替换6个5,所以s=12>6也满足条件II。 v=6时,s=7 替换法:if(n>7) n=6+n%2 由1(6-1)+2(3-1)+3(2-1)+4(3-1)+5(6-1) = 45 < 68知,s=7满足条件I,且最多可替换5个6,所以s=7>5也满足条件II。 可以看出,“模优化”将无论多么大的输入样本减少到50个以内,极大地减少了计算量,从而显著提高运行效率。而“模优化”的关键就是“抽屉原理”。

Comments

rexdf: (function(){ var p = { url:location.href, to:’qqmail’, desc:’’, /默认分享理由(可选)/ summary:’’,/摘要(可选)/ title:’’,/分享标题(可选)/ site:’’,/分享来源 如:腾讯网(可选)/ pics:’’ /分享图片的路径(可选)/ }; var s = []; for(var i in p){ s.push(i + ‘=’ + encodeURIComponent(p[i] ’’)); } document.write([”’].join(“”)); })();

rexdf: #include using namespace std;

int main()
{
cout<<"Hello World!"<<endl;
system("pause");
return 0;
}

asdfasdfasdf: text

SkyWorld:

SkyWorld:

rexdf: 你好 现在回复可用了

Comments