user-0 提问: 有记忆功能的动态规划看不懂啊。。

回复:
user: user-1
content: 仅供参考：//http://www.cnblogs.com/chinazhangjie/archive/2010/11/16/1878400.html //多边形游戏 //描述 //    一个多边形，开始有n个顶点。每个顶点被赋予一个正整数值，每条边被赋予一个运算符“+”或“*”。所有边依次用整数从1到n编号。 //    现在来玩一个游戏，该游戏共有n步： //    第1步，选择一条边，将其删除 //    随后n-1步，每一步都按以下方式操作： //    （1）选择一条边E以及由E连接着的2个顶点v1和v2； //    （2）用一个新的顶点取代边E以及由E连接着的2个顶点v1和v2，将顶点v1和v2的整数值通过边E上的运算得到的结果值赋给新顶点。 //    最后，所有边都被删除，只剩一个顶点，游戏结束。游戏得分就是所剩顶点上的整数值。那么这个整数值最大为多少？ //输入 //    第一行为多边形的顶点数n（n ≤ 20），其后有n行，每行为一个整数和一个字符， //    整数为顶点上的正整数值，字符为该顶点到下一个顶点间连边上的运算符“+”或“*” //    （最后一个字符为最后一个顶点到第一个顶点间连边上的运算符）。 //输出 //    输出仅一个整数，即游戏所计算出的最大值。 //样例输入 //4 //4 * //5 + //5 + //3 + //样例输出 //70 // //分析： //最优子结构性质 //按照顺时针顺序，多边形和顶点的顺序可以写成： //  op[1], v[1], op[2], v[2], …, op[n], v[n] //在所给多边形中，从顶点i(1 <= i <= n)开始，长度为j(链中有j个顶点)的顺时针链p(i，j) 可表示为 //v[i], op[i+1], v[i+1],…, op[i+j-1], v[i+j-1] // //如果这条链在op[i + s]处进行最后一次合并运算(1 <= s <= j-1)，则可在op[i+s]处将链分割为2个子链： // //从i开始长度为s的链：  p(i，s) //从i + s开始，长度为j - s的链：p(i + s，j-s)。 //设: //m1是对子链p(i，s)的任意一种合并方式得到的值，而a和b分别是在所有可能的合并中得到的最小值和最大值。 // //m2是p(i+s，j-s)的任意一种合并方式得到的值，而c和d分别是在所有可能的合并中得到的最小值和最大值。 // //依此定义有a <= m1 <= b，c <= m2 <= d // //(1)当op[i+s] = ‘+’时，显然有a + c <= m <= b + d // //(2)当op[i+s] = ’*’时，有 // //min {ac，ad，bc，bd} <= m <= max {ac，ad，bc，bd} //换句话说，主链的最大值和最小值可由子链的最大值和最小值得到。 #include <windows.h> #include <stdio.h> #include <string.h> #include <conio.h> #include <locale.h> int n; char o[21];//op int  d[21];//vertex data int maxv; struct SEGINFO {//阶段信息     int maxv;     int minv; } sg[21][21],si; int X,Y; void getXY() {     CONSOLE_SCREEN_BUFFER_INFO csbi;     GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&csbi);     X=csbi.dwCursorPosition.X;     Y=csbi.dwCursorPosition.Y; } void gotoXY(int x, int y) {     COORD coord = {x, y};     SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); } void ConPrintAt(int x, int y, char *CharBuffer, int len) {     DWORD count;     COORD coord = {x, y};     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     SetConsoleCursorPosition(hStdOut, coord);     WriteConsole(hStdOut, CharBuffer, len, &count, NULL); } void ClearCon() {     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     COORD coord = {0, 0};     DWORD count;     CONSOLE_SCREEN_BUFFER_INFO csbi;     if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) {         FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);         FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);         SetConsoleCursorPosition(hStdOut, coord);     } } void show(char *p) {     int y,x;     static char ss[128];      for (y=1;y<n;y++) {         sprintf(ss,"%c",o[y]);         ConPrintAt(0,y,ss,1);         for (x=1;x<n;x++) {             sprintf(ss,"%2d ",sg[y][x].maxv);             ConPrintAt(x*3,y,ss,3);         }     }     sprintf(ss,"%-128s",p);     ConPrintAt(1,n,ss,128);     gotoXY(0,n); } void pmt(char *p) {     static char ss[128];      sprintf(ss,"%-128s",p);     ConPrintAt(1,n,ss,128);     gotoXY(0,n); } void getmaxmin(int i, int s, int j) {// 从i开始，长度为j，s为切分位置     int minL;     int maxL;     int minR;     int maxR;     int r;     int mm[4];     int vmin;     int vmax;     static char p[128];      minL=sg[i][s].minv;     maxL=sg[i][s].maxv;         sprintf(p,"总长j:%d 上开始i:%d,长度  s:%d,maxL:%d",j,i,s  ,maxL);pmt(p);getXY();gotoXY(s    *3,i);getch();gotoXY(X,Y);       r=(i+s-1)%(n-1)+1;     minR=sg[r][j - s].minv;     maxR=sg[r][j - s].maxv;     sprintf(p,"总长j:%d 下开始r:%d,长度j-s:%d,maxR:%d",j,r,j-s,maxR);pmt(p);getXY();gotoXY((j-s)*3,r);getch();gotoXY(X,Y);      if (o[r] == '+') {// 处理加法         si.minv=minL + minR;         si.maxv=maxL + maxR;    sprintf(p,"上下合并maxv:%d=maxL:%d + maxR:%d",si.maxv,maxL,maxR);pmt(p);getch();     } else {// 处理乘法         mm[0]=minL * minR;         mm[1]=minL * maxR;         mm[2]=maxL * minR;         mm[3]=maxL * maxR;         vmin=mm[0];         vmax=mm[0];         for (i=1;i<4;i++) {             if (mm[i]<vmin) vmin=mm[i];             if (mm[i]>vmax) vmax=mm[i];         }         si.minv=vmin;         si.maxv=vmax;           sprintf(p,"上下合并maxv:%d=maxL:%d * maxR:%d",si.maxv,maxL,maxR);pmt(p);getch();     } } void pg() {     int i,j,s;     static char p[128];      ClearCon();     for (i=1;i<n;i++) {         sg[i][1].maxv=d[i];         sg[i][1].minv=d[i];     }     show("init");getch();     for (j=2;j<n;j++) {//长度         for (i=1;i<n;i++) {//起点             for (s=1;s<j;s++) {//子切分位置                 getmaxmin(i,s,j);                 if (sg[i][j].minv > si.minv) sg[i][j].minv=si.minv;                  sprintf(p,"sg[开始i:%d][长度j:%d].maxv:%d < maxv=%d ?",i,j,sg[i][j].maxv,si.maxv);pmt(p);                 getXY();gotoXY(j*3,i);getch();gotoXY(X,Y);                 if (sg[i][j].maxv < si.maxv) {                     sg[i][j].maxv=si.maxv;                     show("");                     sprintf(p,"Yes, sg[开始i:%d][长度j:%d].maxv:%d <-- maxv=%d",i,j,sg[i][j].maxv,si.maxv);pmt(p);                     getXY();gotoXY(j*3,i);getch();gotoXY(X,Y);                 } else {                     sprintf(p,"sg[开始i:%d][长度j:%d].maxv:%d < maxv=%d ? No",i,j,sg[i][j].maxv,si.maxv);pmt(p);                     getch();                 }             }         }     }     sprintf(p,"规划完毕，下一步计算总maxv...");pmt(p);getch();     maxv=sg[1][n-1].maxv;     sprintf(p,"总maxv=sg[1][n-1].maxv:%d",maxv);pmt(p);     getXY();gotoXY((n-1)*3,1);getch();gotoXY(X,Y);     for (i=2;i<n;i++) {         sprintf(p,"总maxv:%d < sg[开始i:%d][长度n-1:%d].maxv:%d ?",maxv,i,n-1,sg[i][n-1].maxv);pmt(p);         getXY();gotoXY((n-1)*3,i);getch();gotoXY(X,Y);         if (maxv < sg[i][n-1].maxv) {             maxv=sg[i][n-1].maxv;             sprintf(p,"Yes,总maxv:%d <-- sg[开始i:%d][长度n-1:%d].maxv:%d",maxv,i,n-1,sg[i][n-1].maxv);pmt(p);             getXY();gotoXY((n-1)*3,i);getch();gotoXY(X,Y);         } else {             sprintf(p,"总maxv:%d < sg[开始i:%d][长度n-1:%d].maxv:%d ? No",maxv,i,n-1,sg[i][n-1].maxv);pmt(p);             getch();         }     }     sprintf(p,"计算出总maxv:%d",maxv);pmt(p);getch();     gotoXY(0,n+1); }  int main() {     int i;     char b[2];      setlocale(LC_ALL,"chs");     scanf("%d",&n);     for (i=1;i<=n;i++) {         scanf("%d%1s",&d[i],b);o[(i%n)+1]=b[0];     }     n++;     pg();//PolyGame     printf("%d\n",maxv);     return 0; } //4 //1 + //2 + //4 + //8 +

user: user-2
content: 1) 自顶向下通常指的递归, 自底向上指的递推 2) 不知道V(1,2)是什么意思, 看伪码是除0行0列外都是计算出来的

user: user-0
content: 类似自底向上动态规划算法法使用的表格.。。这句话该怎么理解