题解参考:http://www.cnblogs.com/peaceful-andy/archive/2012/08/14/2638907.html
很久很久以前……我一直以为记忆化搜索就是dp,dp就是记忆化搜索……多么悲哀的认识……
动态规划是“填表格”的顺序依次递推,记忆化搜索说白了就是搜索的一种,树型,二者的相同点就是,边运行边记忆,对于计算过的都存起来,不再重复计算。
1 #include <iostream> 2 using namespace std; 3 4 const int N = 1005; 5 const int M = 25; 6 int ans[N][M],segs[M],ints[N]; 7 int n,m; 8 9 int DFS(int posInt,int posSeg) 10 { 11 if (ans[posInt][posSeg] != -1) 12 return ans[posInt][posSeg]; 13 //已经用完了n个数 或 分完m个数段了 14 if (posSeg > m || posInt > n) 15 { 16 ans[posInt][posSeg] = 0; 17 return ans[posInt][posSeg]; 18 } 19 //判断,即使取了posInt位置的数,能不能取完余下的数段 20 int remainedInts = n - posInt + 1; 21 int remainedSegs = 0; 22 for (int i = posSeg;i <= m;i ++) 23 remainedSegs += segs[i]; 24 //余下的数段的长度之和比余下的数字的个数还大 25 if (remainedSegs > remainedInts) 26 { 27 ans[posInt][posSeg] = 0; 28 return ans[posInt][posSeg]; 29 } 30 //若能走到这一步,说明posInt位置的数可以不作为第posSeg个数段的起始数字 31 int max; 32 //以第posInt个数为起始,取seg[posSeg]个连续的数的和 33 int sum = 0; 34 for (int i = posInt;i < posInt + segs[posSeg];i ++) 35 sum += ints[i]; 36 max = sum + DFS(posInt + segs[posSeg],posSeg + 1); 37 //以第posInt + 1个数为起始,取seg[posSeg]个连续的数的和 38 int temp = DFS(posInt + 1,posSeg); 39 max = max > temp ? max : temp; 40 ans[posInt][posSeg] = max; 41 return ans[posInt][posSeg]; 42 } 43 44 int main () 45 { 46 while (scanf("%d",&n) != -1 && n != 0) 47 { 48 memset(ans,-1,sizeof(ans)); 49 scanf("%d",&m); 50 for (int i = 1;i <= m;i ++) 51 scanf("%d",&segs[i]); 52 for (int i = 1;i <= n;i ++) 53 scanf("%d",&ints[i]); 54 printf("%d\n",DFS(1,1)); 55 } 56 return 0; 57 }
hdoj1244
思路:
第一次,只用了简单地深搜,超时。于是自然就想到记忆搜索,用了就过啦。
ints是一维数组,保存所有数字。segs是一位数组,保存所有数段的长度。
ans是二维数组。ans[i][j]保存以第i个数字开始(但第i个数字不一定被取到,只是从第i个数字开始考虑),计算j,j+1...m段数段之和的最大值。(①划分子问题)本题要求的便是ans[1][1]。
ans[i][j]=max{sum+ans[i+segs[j]][j+1],ans[i+1][j]}。(②写递推关系式)max{}中的两个数的区别就在于,是否以第i个数作为第j个数段的起始数字。
——————————
dfs模板://记忆化搜索的精髓就是*里面的啦*
如果达到边界就*保存状态*并return;
如果不符合要求就*保存状态*并return;
状态转移方程进行选择;
*保存状态*并return;
——————————
另:学姐说
if else会比 ?: 慢很多,能用后者不用前者!
时间: 2025-01-20 04:24:48