// C++ Versionintn,t;inttcost[103],mget[103];intans=0;voiddfs(intpos,inttleft,inttans){if(tleft<0)return;if(pos==n+1){ans=max(ans,tans);return;}dfs(pos+1,tleft,tans);dfs(pos+1,tleft-tcost[pos],tans+mget[pos]);}intmain(){cin>>t>>n;for(inti=1;i<=n;i++)cin>>tcost[i]>>mget[i];dfs(1,t,0);cout<<ans<<endl;return0;}
具体到本题上,我们在朴素的 DFS 的基础上,增加一个数组 mem 来记录每个 dfs(pos,tleft) 的返回值。刚开始把 mem 中每个值都设成 -1(代表没求解过)。每次需要访问一个状态时,如果相应状态的值在 mem 中为 -1,则递归访问该状态。否则我们直接使用 mem 中已经存储过的值即可。
通过这样的处理,我们确保了每个状态只会被访问一次,因此该算法的的时间复杂度为 。
1 2 3 4 5 6 7 8 91011121314151617181920212223
// C++ Versionintn,t;inttcost[103],mget[103];intmem[103][1003];intdfs(intpos,inttleft){if(mem[pos][tleft]!=-1)returnmem[pos][tleft];// 已经访问过的状态,直接返回之前记录的值if(pos==n+1)returnmem[pos][tleft]=0;intdfs1,dfs2=-INF;dfs1=dfs(pos+1,tleft);if(tleft>=tcost[pos])dfs2=dfs(pos+1,tleft-tcost[pos])+mget[pos];// 状态转移returnmem[pos][tleft]=max(dfs1,dfs2);// 最后将当前状态的值存下来}intmain(){memset(mem,-1,sizeof(mem));cin>>t>>n;for(inti=1;i<=n;i++)cin>>tcost[i]>>mget[i];cout<<dfs(1,t)<<endl;return0;}
// C++ Versionintdfs(inti){if(mem[i]!=-1)returnmem[i];intret=1;for(intj=1;j<i;j++)if(a[j]<a[i])ret=max(ret,dfs(j)+1);returnmem[i]=ret;}intmain(){memset(mem,-1,sizeof(mem));// 读入部分略去cout<<dfs(n)<<endl;}