一道记忆搜索题,记忆搜索题就是搜索的形式+DP的思想!
题目:
1 #include<stdio.h> 2 #include<string.h> 3 //#include<stdlib.h> 4 /*#include<iostream> 5 #include<algorithm> 6 using namespace std;*/ 7 8 int getmax(int x, int y){ 9 return x > y ? x : y; 10 } 11 12 typedef struct{ 13 int x; 14 int y; 15 }List; 16 List list[10001]; 17 18 int dir[4][2]={0, -1, -1, 0, 0, 1, 1, 0}; 19 20 21 int main(){ 22 int n, k, block[101][101], i, j, ii, jj, dp[101][101], max, lastmax, startx, starty, start, num; 23 while(scanf("%d %d", &n, &k) && (n != -1 || k != -1)){ 24 max = -1; 25 for(i = 0; i < n; i ++){ 26 for(j = 0; j < n; j ++){ 27 scanf("%d", &block[i][j]); 28 max = getmax(max, block[i][j]); 29 } 30 } 31 memset(dp, -1, sizeof(dp)); 32 dp[0][0] = block[0][0]; 33 start = dp[0][0]; 34 startx = 0; 35 starty = 0; 36 num = 0; 37 lastmax = dp[0][0]; 38 do{ 39 for(i = 0; i < 4; i ++){ 40 if(block[startx][starty] == max){ 41 break; 42 } 43 for(j = 1; j <= k; j ++){ 44 ii = startx + dir[i][0] * j; 45 jj = starty + dir[i][1] * j; 46 if(ii < 0 || jj < 0 || ii >= n || jj >= n || block[ii][jj] <= block[startx][starty]){ 47 continue; 48 } 49 dp[ii][jj] = getmax(dp[ii][jj], start + block[ii][jj]); 50 lastmax = getmax(dp[ii][jj], lastmax); 51 list[num].x = ii; 52 list[num ++].y = jj; 53 } 54 } 55 if(num == 0){ 56 num --; 57 continue; 58 } 59 startx = list[-- num].x; 60 starty = list[num].y; 61 start = dp[startx][starty]; 62 }while(num != -1); 63 printf("%d\n", lastmax); 64 } 65 return 0; 66 }
望大神指点,个人觉得跟下面的正确代码时间复杂度差不多啊!
正确代码:
1 #include<stdio.h> 2 #include<string.h> 3 4 int map[105][105]; 5 int value[105][105]; 6 int dir[4][2]={0,1,0,-1,1,0,-1,0}; 7 int n,k; 8 9 int dfs(int sx,int sy) 10 { 11 int i,j,x,y,max=0,temp; 12 if(value[sx][sy]!=-1) //该点已经计算过,直接返回值 13 return value[sx][sy]; 14 for(i=0;i<4;i++) //2个循环控制该点所能走的地方 15 for(j=1;j<=k;j++) 16 { 17 x=sx+dir[i][0]*j; 18 y=sy+dir[i][1]*j; 19 if(x<0||x>=n||y<0||y>=n||map[x][y]<=map[sx][sy]) //剪枝 20 continue; 21 temp=dfs(x,y); 22 if(temp>max) //max保存由该点所能到达之处能吃到的最大奶酪数 23 24 max=temp; 25 } 26 value[sx][sy]=map[sx][sy]+max; //得到由该点出发所能吃到的最大奶酪数,保存在value里 27 return value[sx][sy]; 28 } 29 30 int main() 31 { 32 int i,j; 33 while(scanf("%d%d",&n,&k)!=EOF) 34 { 35 if(n==-1&&k==-1) 36 break; 37 memset(value,-1,sizeof(value)); //初始化数组(不能为0) 38 for(i=0;i<n;i++) 39 for(j=0;j<n;j++) 40 scanf("%d",&map[i][j]); 41 printf("%d\n",dfs(0,0)); 42 } 43 return 0; 44 }
总结:
尽量不要用do....while();