int solve(int i,int j) { return a[i][j] + (i==n ?0:max(solve(i+1,j),solve(i+1,j+1)); }
用直接递归的方法计算状态转移方程,效率往往十分低下。其原因是相同的子问题被重复计算了多次。
int i, j; for(j = 1; j <= n; j++) d[n][j] = a[n][j]; for(i = n-1; i >= 1; i——) for(j = 1; j <= i; j++) d[i][j] = a[i][j] + max(d[i+1][j],d[i+1][j+1]);
程序的时间复杂度显然是O(n2),但为什么可以这样计算呢?原因在于:i是 逆序枚举的,因此在计算d[i][j]前,它所需要的d[i+1][j]和d[i+1][j+1]一定已经计算出来了。
int solve(int i, int j){ if(d[i][j] >= 0) return d[i][j]; return d[i][j] = a[i][j] + (i == n ? 0 : max(solve(i+1,j),solve(i+1,j+1)));
9.2.1 DAG模型
嵌套矩形问题。有n个矩形,每个矩形可以用两个整数a、b描述,表示它的长和宽。矩
形X(a,b)可以嵌套在矩形Y(c, d)中,当且仅当a<c,b<d,或者b<c,a<d(相当于把矩
形X旋转90°)。例如,(1, 5)可以嵌套在(6, 2)内,但不能嵌套在(3, 4)内。你的任务是选出尽
量多的矩形排成一行,使得除了最后一个之外,每一个矩形都可以嵌套在下一个矩形内。如
果有多解,矩形编号的字典序应尽量小。
int dp(int i) { int& ans = d[i]; if(ans>0) return ans; for(int j = 0;j<n;j++) { if(G[i][j]) ans = max(ans,dp(j)+1); } return ans; }
原题还有一个要求:如果有多个最优解,矩形编号的字典序应最小。还记得第6章中的
例题“理想路径”吗?方法与其类似。将所有d值计算出来以后,选择最大d[i]所对应的i。如
果有多个i,则选择最小的i,这样才能保证字典序最小。接下来可以选择d(i)=d(j)+1且
(i,j)∈E的任何一个j。为了让方案的字典序最小,应选择其中最小的j
void print_ans(int i) {2 printf("%d ", i); for(int j = 1; j <= n; j++) if(G[i][j] && d[i] == d[j]+1){ print_ans(j); break; } }
int dp(int s) { int& ans = d[s]; if(ans>=0) return ans; for(int i = 0;i<n;i++) { if(s>=v[i]) ans = max(ans,dp(s-v[i])+1); } return ans; }
原文:http://www.cnblogs.com/qlky/p/5269474.html