|
设有N*N的方格图(N<=8),我们将其中的某些方格中填入正整数,二其他的方格中则放入数字0。如下图所示(见样例): ->向右 A 0 0 0 0 0 0 0 0 0 0 13 0 0 6 0 0 0 0 0 0 7 0 0 0 0 0 0 14 0 0 0 0 0 21 0 0 0 5 0 0 0 0 15 0 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 B 某人从图的左上角的A点出发,可以向下行走,也可以向右走,知道到达右下角的B点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。 此人从A点到B点共走两次,试找出2条这样的路径,使得取得的数之和为最大。 输入: 输入的第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。 输出: 只需输出一个整数,表示2条路径上取得的最大的和。 样例: 输入 8 2 3 13 2 6 6 3 5 7 4 4 14 5 2 21 5 6 4 6 3 15 7 2 14 0 0 0 输出 67 |
|
|
|
又是方格取数! 记忆化搜索
|
|
|
何为记忆化搜索?请高人不吝赐教.
在下洗耳恭听,万分感谢! |
|
|
记忆化搜索=搜索的形式+DP思想。
这题最好用BFS+DP |
|
|
何为DP呢?
敢请高人再指点迷津,此题对我非常重要,谢谢!!!! |
|
|
DP 动态规划!自己多看看书吧!
|
|
|
英语有点菜,
如何将广度优先与动态规划结合起来呢? 此题关键要求两条路径之和最大,动态规划的最优解递推公式如何呢? |
|
|
哪位高手能给个伪代码?
谢谢!! |
|
|
/*
Problem 4 Written by one_add_one (December 2 2000) Email: one_add_one @163.net */ #include <stdio.h> #define MAX 50 int max(int a,int b){ if (a>b) return a;else return b; } main(){ int pa[MAX][MAX],pb[MAX][MAX],p[MAX][MAX]; int n,i,j,k; int *a=&pa[0][0],*b=&pb[0][0],*swap; for (j=0;j<MAX;j++) for (i=0;i<MAX;i++) p[j][i]=0; printf("Input:");scanf ("%d",&n); for (j=0;j<MAX;j++) for (i=0;i<MAX;i++) *(a+j*MAX+i)=*(b+j*MAX+i)=0; do{ printf(">");scanf("%d %d %d",&i,&j,&k); p[i][j]=k; } while(i!=0 || j!=0 || k!=0); for (j=1;j<=n;j++) for (i=j;i<=n;i++){ *(a+j*MAX+i)=*(a+MAX+i-1)+p[1][i]; } for (k=2;k<=n;k++){ for (j=1;j<=n;j++) for (i=j;i<=n;i++){ if (j==1) *(b+j*MAX+i)=*(a+j*MAX+i)+p[k][1]; else *(b+j*MAX+i)=max(*(a+j*MAX+i),*(b+(j-1)*MAX+i))+p[k][j]; } swap=a;a=b;b=swap; for (j=1;j<=n;j++) for (i=j;i<=n;i++){ if (i==1) *(b+j*MAX+i)=*(a+j*MAX+i); else{ if (j==i) *(b+j*MAX+i)=max(*(b+(j-1)*MAX+i),*(a+j*MAX+i)); else *(b+j*MAX+i)=max(*(b+j*MAX+i-1),*(a+j*MAX+i))+p[k][i]; } } swap=a;a=b;b=swap; } printf("%d\n",pa[n][n]); } |
|
|
这个题可以直接用DP,复杂度是O(n^3)
不过比较难想... 上面的程序就用的这种方法.. 也可以用搜索+DP...复杂度高一点... |
|
|
#include <stdio.h>
#include <stdlib.h> int n=0,mmax,result=0,a[64][3],path[16],p1[16],p2[16],*b,**ff; //f:use in getmax2 //ff:use through the program //mmax:temporary max through the program; //result:the final max; void error() { printf("Alloc Memory Error!"); exit(1); } void print() { int i; printf("Path 1:\n%d",p1[1]); for(i=2;i<=p1[0];i++) printf("--%d",p1[i]); printf("\nPath 2:\n%d",p2[1]); for(i=2;i<=p2[0];i++) printf("--%d",p2[i]); printf("\nMAX=%d\n",result); } void getmax2(int k) { int next,i,j,max,**f,t=0; //max:temporary in getmax2 f=(int **)malloc(sizeof(int *)*n); for(i=0;i<n;i++) { f[i]=(int *)malloc(sizeof(int)*2); if(!f[i]) error(); } for(i=0;i<n;i++) if(b[i]) { f[i][0]=a[i][2]; f[i][1]=0; } for(i=n-2;i>=0;i--) if(b[i]) { max=0; next=0; for(j=i+1;j<n;j++) if(b[j] && f[j][0]>max && a[j][0]>=a[i][0] && a[j][1]>=a[i][1]) { max=f[j][0]; next=j; } if(next) { f[i][0]+=max; f[i][1]=next; } } max=0;next=0; for(i=0;i<n;i++) if(max<f[i][0] && b[i]) { max=f[i][0]; next=i; } mmax+=max; if(mmax>result) { result=mmax; p1[0]=k+1; for(i=0;i<=k;i++) p1[i+1]=path[i]; while(f[next][1]) { p2[++t]=next; next=f[next][1]; } p2[t+1]=next; p2[0]=t+1; //print();//在此加入print(),可打印整个搜索过程 } for(i=0;i<n;i++) free(f[i]); free(f); } void calmax(int kk) { int i; mmax=0; for(i=0;i<=kk;i++) mmax+=a[path[i]][2]; getmax2(kk); } void produceff() { int i,j,temp; for(i=0;i<=n-1;i++) { temp=0; for(j=i+1;j<n;j++) if(a[j][0]>=a[i][0] && a[j][1]>=a[i][1]) temp++; ff[i]=(int *)malloc(sizeof(int)*(temp+1)); if(!ff[i]) error(); ff[i][0]=temp; //save the total number temp=0; for(j=i+1;j<n;j++) if(a[j][0]>=a[i][0] && a[j][1]>=a[i][1]) ff[i][++temp]=j; } } void find(int k)//BFS { int i; calmax(k); for(i=1;i<=ff[path[k]][0];i++) { k++; path[k]=ff[path[k-1]][i]; b[path[k]]=0; find(k); b[path[k]]=1; k--; } } void main() { FILE *file; int x,y,i,j; //read data file=fopen("xt4.txt","r"); if(!file) {printf("File Open Error!");exit(1);} fscanf(file,"%d",&x); fscanf(file,"%d",&x); while(x) { a[n][0]=x; fscanf(file,"%d%d",&x,&y); a[n][1]=x;a[n][2]=y; n++; fscanf(file,"%d",&x); } fclose(file); //initialize b=(int *)malloc(sizeof(int)*n); ff=(int **)malloc(sizeof(int *)*n); if(!b||!ff) error(); //getmax=max{every1+getmax2} produceff(); for(i=0;i<n;i++) { for(j=0;j<n;j++) b[j]=1; path[0]=i; b[i]=0; find(0); } print(); //destroy free(b); for(i=0;i<n;i++) free(ff[i]); free(ff); } |
|
|
BFS+DP
|
|
|
除了找出最优解外,还可将所有路径输出!
|
|
|
Dymatic Programming:
每走一步一个状态, 这样一个matrix被分为2n-1个阶段。 |
|
|
第k 个阶段,即为从(1,k)到(k,1)
的右下对角线。 设第k个阶段的A(x1,y1), B(x2,y2)两个节点, 那么从(1,1)到A(x1,y1)有很多路径path(A),到B(x2,y2)也有很多路径path (B), 虽然路多,组合多,但max{path(A)+path(B)} 的值只有一个,这个值即是我们要用动态规划法 探索得到并保存的,所以此题关键在于:在第k 个阶段,找出关于任意两点A,B的max值。 (注意是任意两点A,B,且A,B可相同!!!) 步步推进,即可搜出最后解。 设maxpathes[k][A][B] 为在第k阶段,两条路径分别行至A和B两节点的最大路径和 递推公式如下: k=1 maxpathes[1][(1,1)][(1,1)]=0; k>=2 maxpathes[k][A][B]={ MAX { maxpathes[k-1][A*][B*]+A格上的值 | if A=B}, MAX { maxpathes[k-1][A*][B*]+A格上的值+B格上的值 | if A<>B}} A* 属于 可达A的节点集合,B* 属于 可达B的节点集合 |
|
|
小提示:
在将matrix划分后, 对任一点(x,y)都有: y=k+1-x (k为当前阶段值) |
|