??xml version="1.0" encoding="utf-8" standalone="yes"?>久久久久波多野结衣高潮,久久婷婷五月综合国产尤物app,亚洲精品成人久久久http://www.shnenglu.com/JulyRina/category/21058.htmlwelcome to July Rina's blogzh-cnMon, 09 Mar 2015 18:34:01 GMTMon, 09 Mar 2015 18:34:01 GMT60E_婚姻问题?/title><link>http://www.shnenglu.com/JulyRina/archive/2015/03/09/209981.html</link><dc:creator>JulyRina</dc:creator><author>JulyRina</author><pubDate>Mon, 09 Mar 2015 10:57:00 GMT</pubDate><guid>http://www.shnenglu.com/JulyRina/archive/2015/03/09/209981.html</guid><wfw:comment>http://www.shnenglu.com/JulyRina/comments/209981.html</wfw:comment><comments>http://www.shnenglu.com/JulyRina/archive/2015/03/09/209981.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/JulyRina/comments/commentRss/209981.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/JulyRina/services/trackbacks/209981.html</trackback:ping><description><![CDATA[问题来自于一?#8220;3分钟怺”zdQ参加活动的有n位男士和n位女士。要求每位男士都要和所有的奛_q行短暂的单独交,qؓ她们打分Q然后按照喜Ƣ程度,Ҏ一位女士进行排序;同样的,每位奛_也要Ҏ有男士进行打分和排序?br /> 在这之后我们为选择{略n位男士和n位女士配寏V得在婚后不会?#8220;”的情况发生?br /> q里?#8220;”是什么意思:<span style="font-size: 10pt; color: red;">囄来自|络Q仅作D例之?/span><br /> <img src="http://www.shnenglu.com/images/cppblog_com/julyrina/E_婚姻问题.png" width="833" height="598" alt="" /><br /> 如果以下两种情况之一发生Q则会发生出轨: <ol> <li>如果W一对夫M的妻子在婚后觉得自己的丈夫没有第二对夫妻中的丈夫帅;W二对夫M的丈夫同样也觉得自己的妻子没有第一对夫M的妻子漂?/li> <li>如果W一对夫M的丈夫在婚后觉得自己的妻子没有第二对夫妻中的d;W二对夫M的妻子同样也觉得自己的丈夫没有第一对夫M的丈夫帅</li> </ol> 解决E_婚姻的算法之一Q?br /> <strong>延迟认可法QGale-Shapley法Q?/strong><br /> 先对所有男士进行落选标讎ͼU其q。当存在自由hQ进行以下操作:<br /> <ol> <li>每一位自q在所有尚未拒l她的女士中选择一位被他排名最优先的女士;</li> <li>每一位女士将正在q求她的自由男与其当前男友进行比较,选择其中排名优先的男士作为其男友Q即若自q优于当前男友Q则抛弃前男友;否则保留其男友,拒绝自由甗?/li> <li>若某男士被其奛_抛弃Q重新变成自q?/li> </ol> 在算法执行期_自由男们<strong>d出击</strong>Q依ơ对最喜欢和次喜欢的女人求爱,一旦被接受Q即失去自由w,q入订婚状态;而女Z则采?strong>“守株待兔”</strong>?strong>“喜新厌旧”</strong>{略Q对前来求爱的男士进行选择Q若该男子比未婚夫强Q则悔婚Q选择新的未婚夫;否则拒绝该男子的求婚。被奛_抛弃的男人重莯pnQ重新拥有了q求女h的权?#8212;—当然Q新的追求对象比不过前女友?br /> q样Q在法执行期间Q每个h都有可能订婚多次——也有可能一开始就扑ֈ了自q最爱,从一而终——每订一ơ婚Q女Z的选择׃更有利,而男Z的品呛_来差。只要男女生的数量相{,则经q多轮求婚,订婚Q悔婚和再订婚之后,每位男女最l都会找到合适的伴G——虽然不一定是自己的最爱(男h没能q到自己的最爱,或女人没有等到自q最爱来q求Q,但绝对不会出?#8220;虽然彼此相爱Q却不能在一?#8221;的悲剧,所有h都会l成E_的婚姅R?img src ="http://www.shnenglu.com/JulyRina/aggbug/209981.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/JulyRina/" target="_blank">JulyRina</a> 2015-03-09 18:57 <a href="http://www.shnenglu.com/JulyRina/archive/2015/03/09/209981.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>字典树简?/title><link>http://www.shnenglu.com/JulyRina/archive/2015/03/09/209980.html</link><dc:creator>JulyRina</dc:creator><author>JulyRina</author><pubDate>Mon, 09 Mar 2015 10:55:00 GMT</pubDate><guid>http://www.shnenglu.com/JulyRina/archive/2015/03/09/209980.html</guid><wfw:comment>http://www.shnenglu.com/JulyRina/comments/209980.html</wfw:comment><comments>http://www.shnenglu.com/JulyRina/archive/2015/03/09/209980.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/JulyRina/comments/commentRss/209980.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/JulyRina/services/trackbacks/209980.html</trackback:ping><description><![CDATA[字典树是一U树形数据结构,他有如下特点Q?br />     每个节点都有固定个数的指向儿子节点的指针Q她的儿子某一个节点(如果存在的话Q包含的信息是该节点的下一个字W?br />     根节点不包含字符Q除根节点外每一个节炚w只包含一个字W; 从根节点到某一节点Q\径上l过的字W连接v来,节点对应的字W串Q?每个节点的所有子节点包含的字W都不相同?br /> <strong>例:</strong>作ؓ一个简单的演示Q这里我们稍微忽略一些细节。下面的q棵树就是一个简单的<u>字典?/u>的例子:<br /><img src="http://www.shnenglu.com/images/cppblog_com/julyrina/字典?1.png" width="696" height="592" alt="" /><br /> <pre><font size="4px">如图所C,如果我们按行存储q些数据Q? <u>apple</u> <u>append</u> <u>and</u> <u>antiy</u> <u>banana</u> <u>band</u> 我们需?+6+3+5+6+4=29 B 的空间? 但是字典树只需?0 B 的空间? q在数据量更大的时候能起到更好的效果?/font></pre> <br /> 字典树能够线性时间范围内实现数据的增删改查?img src ="http://www.shnenglu.com/JulyRina/aggbug/209980.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/JulyRina/" target="_blank">JulyRina</a> 2015-03-09 18:55 <a href="http://www.shnenglu.com/JulyRina/archive/2015/03/09/209980.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【算法导论(W三版)】第二章学习W记http://www.shnenglu.com/JulyRina/archive/2015/03/07/209956.htmlJulyRinaJulyRinaSat, 07 Mar 2015 07:19:00 GMThttp://www.shnenglu.com/JulyRina/archive/2015/03/07/209956.htmlhttp://www.shnenglu.com/JulyRina/comments/209956.htmlhttp://www.shnenglu.com/JulyRina/archive/2015/03/07/209956.html#Feedback0http://www.shnenglu.com/JulyRina/comments/commentRss/209956.htmlhttp://www.shnenglu.com/JulyRina/services/trackbacks/209956.html 2.3-2 MERGE的改q?br />
void MERGE(int *A, int p,int q, int r) {
    int B[maxn] , i = p , j = q+1 , k = 0;
    while(k < r - p + 1) {
        if(i > q || j <= r && A[i] > A[j]) B[k++] = A[j++];
        else B[k++] = A[i++];
    }
    for(i=0;i<r-p+1;i++) A[p+i] = B[i];
}

2.3-5 二分查找的C++代码
int find(int *a, int l, int r, int value) {
    if(l == r) return l;
    int mid = (l+r) >> 1;
    if(a[mid] >= value) return find(a, l, mid, value);
    else return find(a , mid+1, r , value);
}

*2.3-7 Q这道题其实有O(n)的算法,而且写v来更方便些)q里是O(nlogn)的算?br /> O(nlogn)法思想Q?.首先q行排序Q?.然后枚D每一个小于等于x/2的数S[i]Q二分查扑֯应的x-S[i]是否存在
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010;
bool findx(int *S,int n, int x,int l,int r) {
    if(l > r) return false;
    if(l ==r) return S[l] == x;
    int mid = (l+r) >> 1;
    if(S[mid] >= x) return findx(S, n, x, l, mid);
    else return findx(S, n, x, mid+1, r);
}
bool check(int *S,int n,int x) {
    for(int i=0;S[i]<=x/2 && i < n;i++) {
        if(findx(S, n, x-S[i], i+1, n-1)) return true;
    }
    return false;
}
int main() {
    int S[1010] , x , n;
    while(~scanf("%d%d" , &n , &x)) {
        for(int i=0;i<n;i++) cin >> S[i];
        if(check(S, n, x)) puts("yes");
        else puts("no");
    }
    return 0;
}

O(n)的方法是在数的范围不是特别大的时候(或者数的范围比较大Q此旉用hash的方法)标记的方法,q里假设数的范围<=10000Qƈ且假设数没有重复的情况下Q其他情늨许改变一下就行:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010;

bool check(int *S,int n,int x) {
    bool vis[10001] = {0};
    for(int i=0;i<n;i++) vis[x-S[i]] = true;
    for(int i=0;i<n;i++) if(vis[S[i]]) return true;
    return false;
}
int n ,x , S[maxn];
int main() {
    while(~scanf("%d%d" , &n , &x)) {
        for(int i=0;i<n;i++) cin >> S[i];
        if(check(S, n, x)) puts("yes");
        else puts("no");
    }
    return 0;
}

2-4Q逆序对)Q这道题是在归q排序中得到逆序对,具体见代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010;
int ans;
void merge_sort(int *A, int l,int r) {
    if(l >= r) return;
    int mid = (l+r) >> 1;
    merge_sort(A, l, mid);
    merge_sort(A, mid+1, r);
    int i = l , j = mid+1 ,B[maxn] , k = l;
    while(i <= mid || j <= r) {
        if(i > mid || j <= r && A[j] < A[i]) B[k++] = A[j++] , ans += mid-i+1;
        else B[k++] = A[i++];
    }
    for(i=l;i<=r;i++) A[i] = B[i];
}
int main() {
    int A[maxn] , n;
    while(~scanf("%d" , &n)) {
        for(int i=0;i<n;i++) cin >> A[i];
        ans = 0;
        merge_sort(A, 0, n-1);
        cout << ans << endl;
        //for(int i=0;i<n;i++) cout << A[i] << " "; cout << endl;
    }
    return 0;
}


JulyRina 2015-03-07 15:19 发表评论
]]>
三个入门博弈http://www.shnenglu.com/JulyRina/archive/2015/03/04/209920.htmlJulyRinaJulyRinaWed, 04 Mar 2015 03:16:00 GMThttp://www.shnenglu.com/JulyRina/archive/2015/03/04/209920.htmlhttp://www.shnenglu.com/JulyRina/comments/209920.htmlhttp://www.shnenglu.com/JulyRina/archive/2015/03/04/209920.html#Feedback0http://www.shnenglu.com/JulyRina/comments/commentRss/209920.htmlhttp://www.shnenglu.com/JulyRina/services/trackbacks/209920.htmlQ一Q巴什博奕QBash GameQ:只有一堆n个物品,两个从q堆物品中取物,规定每次臛_取一个,最多取m个。最后取光者得胜? 昄Q如果n=m+1Q那么由于一ơ最多只能取m个,所以,无论先取者拿走多个Q后取者都能够一ơ拿走剩余的物品Q后者取胜。因此我们发C如何取胜的法则:如果n=Qm+1Qr+sQ(rZQ意自然数Qs≤m),那么先取者要拿走s个物品,如果后取者拿走kQ?#8804;m)个,那么先取者再拿走m+1-k个,l果剩下Qm+1Q(r-1Q个Q以后保持这L取法Q那么先取者肯定获胜。MQ要保持l对手留下(m+1Q的倍数Q就能最后获胜? 卻I若n=k*(m+1)Q则后取着胜,反之Q存在先取者获胜的取法?/font> n%(m+1)==0. 先取者必败?/storng> Q二Q威佐夫博奕QWythoff GameQ:有两堆各若干个物品,两个从某一堆或同时从两堆中取同样多的物品,规定每次臛_取一个,多者不限,最后取光者得胜? q种情况下是颇ؓ复杂的。我们用QakQbkQ(ak ≤ bk ,k=0Q?Q?Q?..,n)表示两堆物品的数量ƈU其为局势,如果甲面对(0Q?Q,那么甲已l输了,q种局势我们称为奇异局ѝ前几个奇异局势是Q(0Q?Q、(1Q?Q、(3Q?Q、(4Q?Q、(6Q?0Q、(8Q?3Q、(9Q?5Q、(11Q?8Q、(12Q?0Q? 可以看出,a0=b0=0,ak是未在前面出现过的最自然数,?bk= ak + kQ奇异局势有 如下三条性质Q? 1。Q何自然数都包含在一个且仅有一个奇异局势中? ׃ak是未在前面出现过的最自然数Q所以有ak > ak-1 Q?bk= ak + k > ak-1 + k-1 = bk-1 > ak-1 。所以性质1。成立? 2。Q意操作都可将奇异局势变为非奇异局ѝ? 事实上,若只改变奇异局势(akQbkQ的某一个分量,那么另一个分量不可能在其他奇异局势中Q所以必然是非奇异局ѝ如果QakQbkQ的两个分量同时减少Q则׃其差不变Q且不可能是其他奇异局势的差,因此也是非奇异局ѝ? 3。采用适当的方法,可以非奇异局势变为奇异局ѝ? 假设面对的局势是Qa,bQ,?b = aQ则同时从两堆中取走 a 个物体,变Z奇异局势(0Q?Q;如果a = ak Qb > bkQ那么,取走b - bk个物体,卛_为奇异局势;如果 a = ak Q?b < bk ,则同时从两堆中拿?ak - ab - ak个物?变ؓ奇异局势( ab - ak , ab - ak+ b - akQ;如果a > ak Qb= ak + k,则从W一堆中拿走多余的数量a - ak 卛_Q如果a < ak Qb= ak + k,分两U情况,W一U,a=aj Qj < kQ?从第二堆里面拿走 b - bj 卛_Q第二种Qa=bj Qj < kQ?从第二堆里面拿走 b - aj 卛_? 从如上性质可知Q两个h如果都采用正操作,那么面对非奇异局势,先拿者必胜;反之Q则后拿者取胜? 那么ȝ一个局势(aQbQ,怎样判断它是不是奇异局势呢Q我们有如下公式Q? ak =[kQ?+√5Q?2]Qbk= ak + k Qk=0Q?Q?Q?..,n Ҏ可C取整函? 奇妙的是其中出现了黄金分割数Q?+√5Q?2 = 1?18...,因此,由akQbkl成的矩形近gؓ黄金矩ŞQ由?/Q?+√5Q?Q?#8730;5-1Q?2Q可以先求出j=[aQ?#8730;5-1Q?2]Q若a=[jQ?+√5Q?2]Q那么a = ajQbj = aj + jQ若不等于,那么a = aj+1Qbj+1 = aj+1+ j + 1Q若都不是,那么׃是奇异局ѝ然后再按照上述法则q行Q一定会遇到奇异局ѝ? Q三Q尼姆博奕(Nimm GameQ:有三堆各若干个物品,两个从某一堆取L多的物品Q规定每ơ至取一个,多者不限,最后取光者得胜? q种情况最有意思,它与二进制有密切关系Q我们用QaQbQcQ表C某U局势,首先Q?Q?Q?Q显然是奇异局势,无论谁面对奇异局势,都必然失败。第二种奇异局势是Q?QnQnQ,只要与对手拿C样多的物品,最后都导_0Q?Q?Q。仔l分析一下,Q?Q?Q?Q也是奇异局势,无论Ҏ如何拿,接下来都可以变ؓQ?QnQnQ的情Ş? 计算机算法里面有一U叫做按位模2加,也叫做异或的q算Q我们用W号Q^Q表CU运。这U运和一般加法不同的一Ҏ1^1=0。先看(1Q?Q?Q的按位?加的l果Q? 1 =二进?1 2 =二进?0 3 =二进?1 Q^Q? ——————— 0 =二进?0 Q注意不q位Q? 对于奇异局势(0QnQnQ也一Pl果也是0? M奇异局势(aQbQcQ都有aQ^QbQ^Qc =0? 如果我们面对的是一个非奇异局势(aQbQcQ,要如何变为奇异局势呢Q假?a < b < c,我们只要?c 变ؓ aQ^Qb,卛_,因ؓ有如下的q算l果: aQ^QbQ^Q?aQ^Qb)=(aQ^Qa)Q^Q?bQ^Qb)=0Q^Q?=0。要c 变ؓaQ^QbQ只要从 c中减?c-QaQ^QbQ即可? 莯情况对先取者进行讨论: 异或l果?Q先取者必败,无获胜方法。后取者获胜; l果不ؓ0Q先取者有莯的取法?/font> 拓展Q?/strong> ȝN堆石?两h轮流从Q一堆中d(每次只能取自一?,取最后一颗石子的胜,问先取的人如何获胜? Ҏ上面所qͼN个数异或卛_。如果开始的时候TQ?Q那么先取者必败,如果开始的时候T>0Q那么只要每ơ取出石子得TQ?Q即先取者有莯的方法?/font>

JulyRina 2015-03-04 11:16 发表评论
]]>
多重背包问题http://www.shnenglu.com/JulyRina/archive/2015/02/18/209834.htmlJulyRinaJulyRinaWed, 18 Feb 2015 12:33:00 GMThttp://www.shnenglu.com/JulyRina/archive/2015/02/18/209834.htmlhttp://www.shnenglu.com/JulyRina/comments/209834.htmlhttp://www.shnenglu.com/JulyRina/archive/2015/02/18/209834.html#Feedback0http://www.shnenglu.com/JulyRina/comments/commentRss/209834.htmlhttp://www.shnenglu.com/JulyRina/services/trackbacks/209834.html题目

有NU物品和一个容量ؓV的背包。第iU物品最多有n[i]件可用,每g费用是c[i]Qh值是w[i]。求解将哪些物品装入背包可ɘq些物品的费用d不超q背包容量,且h值d最大?/p>

基本法

q题目和完全背包问题很类伹{基本的方程只需完全背包问题的方程略微一改即可,因ؓ对于WiU物品有n[i]+1U策略:?Ӟ??#8230;…取n[i]件。of[i][v]表示前iU物品恰攑օ一个容量ؓv的背包的最大权|则有状态{ULE:

f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k<=n[i]}

复杂度是O(V*Σn[i])?/p>

转化?1背包问题

另一U好惛_写的基本Ҏ是{化ؓ01背包求解Q把WiU物品换成n[i]?1背包中的物品Q则得到了物品数?#931;n[i]?1背包问题Q直接求解,复杂度仍然是O(V*Σn[i])?/p>

但是我们期望它转化?1背包问题之后能够像完全背包一样降低复杂度。仍然考虑二进制的思想Q我们考虑把第iU物品换成若qg物品Q得原问题中第iU物品可取的每种{略——?..n[i]?#8212;—均能{h于取若干件代换以后的物品。另外,取超qn[i]件的{略必不能出现?/p>

Ҏ是:第iU物品分成若qg物品Q其中每件物品有一个系敎ͼqg物品的费用和价值均是原来的费用和hg以这个系数。ɘq些pL分别?,2,4,...,2^(k-1),n[i]-2^k+1Q且k是满n[i]-2^k+1>0的最大整数。例如,如果n[i]?3Q就这U物品分成系数分别ؓ1,2,4,6的四件物品?/p>

分成的这几g物品的系数和为n[i]Q表明不可能取多于n[i]件的WiU物品。另外这U方法也能保证对?..n[i]间的每一个整敎ͼ均可以用若干个系数的和表C,q个证明可以?..2^k-1?^k..n[i]两段来分别讨论得出,q不难,希望你自己思考尝试一下?/p>

q样将WiU物品分成了O(log n[i])U物品,原问题转化Z复杂度ؓ<math>O(V*Σlog n[i])?1背包问题Q是很大的改q?/p>

下面l出O(log amount)旉处理一件多重背包中物品的过E,其中amount表示物品的数量:

procedure MultiplePack(cost,weight,amount)     
   if cost*amount>=V
      CompletePack(cost,weight)
      return
   integer k=1
   while k<amount
      ZeroOnePack(k*cost,k*weight)
      amount=amount-k
      k=k*2
   ZeroOnePack(amount*cost,amount*weight)

希望你仔l体会这个伪代码Q如果不太理解的话,不妨译成程序代码以后,单步执行几次Q或者头脑加U笔模拟一下,也许׃慢慢理解了?/p>

O(VN)的算?/h2>

多重背包问题同样有O(VN)的算法。这个算法基于基本算法的状态{ULE,但应用单调队列的Ҏ使每个状态的值可以以均摊O(1)的时间求解。由于用单调队列优化的DP已超ZNOIP的范_故本文不再展开讲解。我最初了解到q个Ҏ是在楼天成的“男h八题”qȝ片上?/p>

q里我们看到了将一个算法的复杂度由O(V*Σn[i])改进到O(V*Σlog n[i])的过E,q知道了存在应用出NOIP范围的知识的O(VN)法。希望你特别注意“拆分物品”的思想和方法,自己证明一下它的正性,q将完整的程序代码写出来?/p>

JulyRina 2015-02-18 20:33 发表评论
]]>
完全背包问题http://www.shnenglu.com/JulyRina/archive/2015/02/18/209833.htmlJulyRinaJulyRinaWed, 18 Feb 2015 12:31:00 GMThttp://www.shnenglu.com/JulyRina/archive/2015/02/18/209833.htmlhttp://www.shnenglu.com/JulyRina/comments/209833.htmlhttp://www.shnenglu.com/JulyRina/archive/2015/02/18/209833.html#Feedback0http://www.shnenglu.com/JulyRina/comments/commentRss/209833.htmlhttp://www.shnenglu.com/JulyRina/services/trackbacks/209833.html题目

有NU物品和一个容量ؓV的背包,每种物品都有无限件可用。第iU物品的费用是c[i]Qh值是w[i]。求解将哪些物品装入背包可ɘq些物品的费用d不超q背包容量,且h值d最大?/p>

基本思\

q个问题非常cM?a >01背包问题Q所不同的是每种物品有无限g。也是从每U物品的角度考虑Q与它相关的{略已ƈ非取或不取两U,而是有取0件、取1件、取2?#8230;…{很多种。如果仍然按照解01背包时的思\Qof[i][v]表示前iU物品恰攑օ一个容量ؓv的背包的最大权倹{仍然可以按照每U物品不同的{略写出状态{ULE,像这P

f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k*c[i]<=v}

q跟01背包问题一hO(VN)个状态需要求解,但求解每个状态的旉已经不是常数了,求解状态f[i][v]的时间是O(v/c[i])Qȝ复杂度可以认为是O(V*Σ(V/c[i]))Q是比较大的?/p>

?1背包问题的基本思\加以改进Q得Cq样一个清晰的Ҏ。这说明01背包问题的方E的是很重要,可以推及其它cd的背包问题。但我们q是试图改进q个复杂度?/p>

一个简单有效的优化

完全背包问题有一个很单有效的优化Q是q样的:若两件物品i、j满c[i]<=c[j]且w[i]>=w[j]Q则物品jLQ不用考虑。这个优化的正确性显ӞM情况下都可将价值小费用高得j换成物美价廉的iQ得到至不会更差的Ҏ。对于随机生成的数据Q这个方法往往会大大减物品的件数Q从而加快速度。然而这个ƈ不能改善最坏情늚复杂度,因ؓ有可能特别设计的数据可以一件物品也M掉?/p>

q个优化可以单的O(N^2)地实玎ͼ一般都可以承受。另外,针对背包问题而言Q比较不错的一U方法是Q首先将费用大于V的物品去掉,然后使用cM计数排序的做法,计算用相同的物品中h值最高的是哪个,可以O(V+N)地完成这个优化。这个不太重要的q程׃l出伪代码了Q希望你能独立思考写Z代码或程序?/p>

转化?1背包问题求解

既然01背包问题是最基本的背包问题,那么我们可以考虑把完全背包问题{化ؓ01背包问题来解。最单的x是,考虑到第iU物品最多选V/c[i]Ӟ于是可以把第iU物品{化ؓV/c[i]件费用及价值均不变的物品,然后求解q个01背包问题。这样完全没有改q基本思\的时间复杂度Q但q毕竟给了我们将完全背包问题转化?1背包问题的思\Q将一U物品拆成多件物品?/p>

更高效的转化Ҏ是:把第iU物品拆成费用ؓc[i]*2^k、hgؓw[i]*2^k的若qg物品Q其中k满c[i]*2^k<=V。这是二q制的思想Q因Z最优策略选几件第iU物品,d以表C成若干?^k件物品的和。这h每种物品拆成O(log V/c[i])件物品,是一个很大的改进?/p>

但我们有更优的O(VN)的算法?/p>

O(VN)的算?/h2>

q个法使用一l数l,先看伪代码:

for i=1..N     
   for v=0..V
      f[v]=max{f[v],f[v-cost]+weight}

你会发现Q这个伪代码?a >P01的伪代码只有v的@环次序不同而已。ؓ什么这样一改就可行呢?首先xZ么P01中要按照v=V..0的逆序来@环。这是因保证Wiơ@环中的状态f[i][v]是由状态f[i-1][v-c[i]]递推而来。换句话_q正是ؓ了保证每件物品只选一ơ,保证在考虑“选入Wi件物?#8221;qg{略Ӟ依据的是一个绝无已l选入Wi件物品的子结果f[i-1][v-c[i]]。而现在完全背包的特点恰是每种物品可选无限gQ所以在考虑“加选一件第iU物?#8221;q种{略Ӟ却正需要一个可能已选入WiU物品的子结果f[i][v-c[i]]Q所以就可以q且必须采用v=0..V的顺序@环。这是q个单的E序Z成立的道理?/p>

值得一提的是,上面的伪代码中两层for循环的次序可以颠倒。这个结论有可能会带来算法时间常C的优化?/p>

q个法也可以以另外的思\得出。例如,基本思\中求解f[i][v-c[i]]的状态{ULE显式地写出来,代入原方E中Q会发现该方E可以等价地变Ş成这UŞ式:

f[i][v]=max{f[i-1][v],f[i][v-c[i]]+w[i]}

这个方E用一l数l实玎ͼ便得C上面的伪代码?/p>

最后抽象出处理一件完全背包类物品的过E伪代码Q?/p>

procedure CompletePack(cost,weight)     
   for v=cost..V
      f[v]=max{f[v],f[v-c[i]]+w[i]}

ȝ

完全背包问题也是一个相当基的背包问题,它有两个状态{ULE,分别?#8220;基本思\”以及“O(VN)的算?#8220;的小节中l出。希望你能够对这两个状态{ULE都仔细C会,不仅CQ也要弄明白它们是怎么得出来的Q最好能够自己想一U得到这些方E的Ҏ。事实上Q对每一道动态规划题目都思考其方程的意义以及如何得来,是加深对动态规划的理解、提高动态规划功力的好方法?/p>

JulyRina 2015-02-18 20:31 发表评论
]]>
01背包问题http://www.shnenglu.com/JulyRina/archive/2015/02/18/209832.htmlJulyRinaJulyRinaWed, 18 Feb 2015 12:30:00 GMThttp://www.shnenglu.com/JulyRina/archive/2015/02/18/209832.htmlhttp://www.shnenglu.com/JulyRina/comments/209832.htmlhttp://www.shnenglu.com/JulyRina/archive/2015/02/18/209832.html#Feedback0http://www.shnenglu.com/JulyRina/comments/commentRss/209832.htmlhttp://www.shnenglu.com/JulyRina/services/trackbacks/209832.html题目

有N件物品和一个容量ؓV的背包。第i件物品的费用是c[i]Qh值是w[i]。求解将哪些物品装入背包可价值d最大?/p>

基本思\

q是最基础的背包问题,特点是:每种物品仅有一Ӟ可以选择放或不放?/p>

用子问题定义状态:即f[i][v]表示前i件物品恰攑օ一个容量ؓv的背包可以获得的最大h倹{则其状态{ULE便是:

f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}

q个方程非常重要Q基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要它详细解释一下:“前i件物品放入容量ؓv的背包中”q个子问题,若只考虑Wi件物品的{略Q放或不放)Q那么就可以转化Z个只牉|前i-1件物品的问题。如果不攄i件物品,那么问题p{化ؓ“前i-1件物品放入容量ؓv的背包中”Qhgؓf[i-1][v]Q如果放Wi件物品,那么问题p{化ؓ“前i-1件物品放入剩下的定w为v-c[i]的背包中”Q此时能获得的最大h值就是f[i-1][v-c[i]]再加上通过攑օWi件物品获得的价值w[i]?/p>

优化I间复杂?/h2>

以上Ҏ的时间和I间复杂度均为O(VN)Q其中时间复杂度应该已经不能再优化了Q但I间复杂度却可以优化到O?/p>

先考虑上面讲的基本思\如何实现Q肯定是有一个主循环i=1..NQ每ơ算出来二维数组f[i][0..V]的所有倹{那么,如果只用一个数lf[0..V]Q能不能保证Wiơ@环结束后f[v]中表C的是我们定义的状态f[i][v]呢?f[i][v]是由f[i-1][v]和f[i-1][v-c[i]]两个子问题递推而来Q能否保证在推f[i][v]Ӟ也即在第iơ主循环中推f[v]Ӟ能够得到f[i-1][v]和f[i-1][v-c[i]]的值呢Q事实上Q这要求在每ơ主循环中我们以v=V..0的顺序推f[v]Q这h能保证推f[v]时f[v-c[i]]保存的是状态f[i-1][v-c[i]]的倹{伪代码如下Q?/p>

for i=1..N     
   for v=V..0
      f[v]=max{f[v],f[v-c[i]]+w[i]};

其中的f[v]=max{f[v],f[v-c[i]]}一句恰q当于我们的{ULE?code>f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]}Q因为现在的f[v-c[i]]q当于原来的f[i-1][v-c[i]]。如果将v的@环顺序从上面的逆序Ҏ序的话Q那么则成了f[i][v]由f[i][v-c[i]]推知Q与本题意不W,但它却是另一个重要的背包问题P02最L解决ҎQ故学习只用一l数l解01背包问题是十分必要的?/p>

事实上,使用一l数l解01背包的程序在后面会被多次用到Q所以这里抽象出一个处理一?1背包中的物品q程Q以后的代码中直接调用不加说明?/p>

q程ZeroOnePackQ表C处理一?1背包中的物品Q两个参数cost、weight分别表明qg物品的费用和价倹{?/p>

procedure ZeroOnePack(cost,weight)     
   for v=V..cost
      f[v]=max{f[v],f[v-cost]+weight}

注意q个q程里的处理与前面给出的伪代码有所不同。前面的CZE序写成v=V..0是ؓ了在E序中体现每个状态都按照方程求解了,避免不必要的思维复杂度。而这里既然已l抽象成看作黑箱的过E了Q就可以加入优化。费用ؓcost的物品不会媄响状态f[0..cost-1]Q这是显然的?/p>

有了q个q程以后Q?1背包问题的伪代码可以这样写Q?/p>

for i=1..N     
   ZeroOnePack(c[i],w[i]);

初始化的l节问题

我们看到的求最优解的背包问题题目中Q事实上有两U不太相同的问法。有的题目要?#8220;恰好装满背包”时的最优解Q有的题目则q没有要求必L背包装满。一U区别这两种问法的实现方法是在初始化的时候有所不同?/p>

如果是第一U问法,要求恰好装满背包Q那么在初始化时除了f[0]?其它f[1..V]均设?∞Q这样就可以保证最l得到的f[N]是一U恰好装满背包的最优解?/p>

如果q没有要求必L背包装满Q而是只希望h格尽量大Q初始化时应该将f[0..V]全部设ؓ0?/p>

Z么呢Q可以这L解:初始化的f数组事实上就是在没有M物品可以攑օ背包时的合法状态。如果要求背包恰好装满,那么此时只有定w?的背包可能被价gؓ0的nothing“恰好装满”Q其它容量的背包均没有合法的解,属于未定义的状态,它们的值就都应该是-∞了。如果背包ƈ非必被装满Q那么Q何容量的背包都有一个合法解“什么都不装”Q这个解的hgؓ0Q所以初始时状态的g全部ؓ0了?/p>

q个技巧完全可以推q到其它cd的背包问题,后面也就不再对进行状态{UM前的初始化进行讲解?/p>

一个常C?/h2>

前面的伪代码中有 for v=V..1Q可以将q个循环的下限进行改q?/p>

׃只需要最后f[v]的|倒推前一个物品,其实只要知道f[v-w[n]]卛_。以此类推,对以Wj个背包,其实只需要知道到f[v-sum{w[j..n]}]卛_Q即代码中的

for i=1..N     
   for v=V..0

可以Ҏ

for i=1..n     
   bound=max{V-sum{w[i..n]},c[i]}
   for v=V..bound

q对于V比较大时是有用的?/p>

01背包问题是最基本的背包问题,它包含了背包问题中设计状态、方E的最基本思想Q另外,别的cd的背包问题往往也可以{换成01背包问题求解。故一定要仔细体会上面基本思\的得出方法,状态{ULE的意义Q以及最后怎样优化的空间复杂度?/p>

JulyRina 2015-02-18 20:30 发表评论
]]>
鶹˾þþƷ| 777þþƷһ| þùۺϾƷ| þþƷA㽶| պݺݾþ͵͵ɫۺ0| 99ƷѾþþþþ| Ļþۺ| ƷۺϾþþþþ97| þùƷվ| ӰȷŮAV³ɫԴþ| ŷþþþƷ| þþҹƷ| þþһ| þɫۺһ| þþŮ붯ȺëƬ| þþþ뾫Ʒ| 99þóĻ| þþþþþ| 66ƷۺϾþþþþþ| þ޾Ʒ| ùƷӰ˾þ| þþƷ99Ӱ | ձƷþ| avԾþþþa鶹| ľþþþ| ƷþþþĻһ| 97þþƷƷ| þþ뾫Ʒպ˳ | ŷþþþþþѡ9999| þþƷŷƬ| ҹƷþþþþӰriav| ˾þô߽ۺĻ| þþùƷһ| þþþø߳ۺӰԺ| þҹҹ³³ƬӰ | jizzjizzƷþ| þ99ۺϾƷŮͬ| þþŷղ| ҹþþӰԺ| ɫۺϾþĻ| ҹ޾þþþþþþ|