3,882
社区成员




//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 +
#include <stdio.h>
#include <stdlib.h>
void print(int res[], int num) {
static int L=0;
L++;
printf("%8d:",L);
for (int i=0;i<num;++i) {
printf(" %d", res[i]);
}
printf("\n");
}
void split(int n, int m) {// n表示总数,m表示最大因子
static int res[100];// 保存结果
static int num=-1;// 当前因子下标
if (n<m || n<0 || m<1) return;
num++;
if (0==n) {// 递归终止条件,为0不可再分,直接输出
print(res,num+1);
num--;
return;
} else {
if (n==m) {// 不拆,直接输出
res[num]=m;
print(res,num+1);
num--;
} else {
// 拆分出第一个
res[num]=m;
n=n-m;
if (m>n) m = n; // 最大因子不可能大于总数
for (int i=m;i>=1;--i) {// 循环,第二个因子可以继续拆分,而且按照最大因子不同可以拆分成多个
split(n,i);
}
num--;
}
}
}
void Split(int n) {
if (n<=0) return;
if (100<n) {
printf("Up to 100\n");
return;
}
for (int i=n;i>=1;--i) {
split(n, i);
}
}
void main(int argc,char **argv) {
if (argc<=1) Split(5);
else if (argc>=3) split(atoi(argv[1]),atoi(argv[2]));
else Split(atoi(argv[1]));
}
“给定一个小点的输入,完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门!
递归函数关注以下几个因素
·退出条件
·参数有哪些
·返回值是什么
·局部变量有哪些
·全局变量有哪些
·何时输出
·会不会导致堆栈溢出
http://www.codeproject.com/Articles/418776/How-to-replace-recursive-functions-using-stack-and