百度之星第四题(记忆化搜索)

2024-08-21 16:18

本文主要是介绍百度之星第四题(记忆化搜索),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本日志是本人原创,可以转载,但请注明出处,谢谢......

Labyrinth

Time Limit: 2000/1000 MS (Java/Others) Memory Limit:32768/32768 K (Java/Others)
Total Submission(s): 519 Accepted Submission(s): 174

Problem Description

度度熊是一只喜欢探险的熊,一次偶然落进了一个m*n矩阵的迷宫,该迷宫只能从矩阵左上角第一个方格开始走,只有走到右上角的第一个格子才算走出迷宫,每一次只能走一格,且只能向上向下向右走以前没有走过的格子,每一个格子中都有一些金币(或正或负,有可能遇到强盗拦路抢劫,度度熊身上金币可以为负,需要给强盗写欠条),度度熊刚开始时身上金币数为0,问度度熊走出迷宫时候身上最多有多少金币?

Input

输入的第一行是一个整数TT< 200),表示共有T组数据。
每组数据的第一行输入两个正整数mnm<=100n<=100)。接下来的m行,每行n个整数,分别代表相应格子中能得到金币的数量,每个整数都大于等于-100且小于等于100

Output

对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
每组测试数据输出一行,输出一个整数,代表根据最优的打法,你走到右上角时可以获得的最大金币数目。

Sample Input

2

3 4

1 -1 1 0

2 -2 4 2

3 5 1 -90

2 2

1 1

1 1

Sample Output

Case #1:

18

Case #2:

4

代码解析:

1DFS深度优先的方法

#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

#define LL __int64

bool p[100][100];    //访问标记数组

int dx[3]={-1,1,0};    //DFS准备数组(表示x下标位移的移动量)

int dy[3]={0,0,1};    // DFS准备数组(表示y下标位移的移动量)

int value[110][110];  //存储每个方格的黄金数量

int maxx;          //表示最大结果

int ans;           //临时存放计算DFS的每组结果

int m,n;          //mn

int max(int x,int y){return x>y?x:y;}   //最大值函数

//深度优先遍历

void dfs(int x,int y)

{

       p[x][y]=true;    //标记为已访问

       int i;

       ans+=value[x][y];

       if(x==0&&y==n-1)    //DFS出口,表示遍历到右上角

       {maxx=max(maxx,ans);ans-=value[x][y];return;}    //返回,并恢复现场(包括ans的恢复)

       for(i=0;i<3;i++)

       {

              if(x+dx[i]<m&&y+dy[i]<n&&x+dx[i]>=0&&!p[x+dx[i]][y+dy[i]])  //不能越界,且未被访问

              {

                     dfs(x+dx[i],y+dy[i]);    //分别对该方格的上、下、右进行递归遍历

                     p[x+dx[i]][y+dy[i]]=false;     //遍历结束恢复现场(对p的恢复)

              }

       }

       ans-=value[x][y];    //恢复现场(对ans的恢复)

}

int main()

{

       //freopen("in.txt","r",stdin);

       int i,j,T;

       int count;

       while(scanf("%d",&T)!=EOF)

       {

              count=0;

              while(T--)

              {

                     scanf("%d%d",&m,&n);

                     ans=0;

                     maxx=-1000050;    //最大值初始化为最小可能值

                     memset(value,0,sizeof(value));

                     for(i=0;i<m;i++)

                     {

                            for(j=0;j<n;j++)

                            {

                                   scanf("%d",&value[i][j]);

                                   value[i][n]+=value[i][j];

                            }

                     }

                     memset(p,0,sizeof(p));

                     dfs(0,0);

                     printf("Case#%d:\n",++count);

                     printf("%d\n",maxx);

              }

       }

       return 0;

}

这是最容易想的的方法,然而对于n<=100来说,DFS深度很大会造成超时(Timelimited error

所以这道题显然不能用DFS解决。

2DP动态规划求解

由于题目中说只能向上下和右行进,故如果我们能枚举所有向右行进的时机那么此问题便迎刃而解。

假设:

·dp[i][j]表示从第i-1列适宜位置开始,移动至第i-1列的第j行时向右行进到第i列之前,ans所能积累的最大值。

·d[j][i][k]表示从第i列的第k行移动到第i列的第j行时所积累的和。

那么易知,dp[0][n]即是所求

dp[0][n]=dp[i][n]+d[0][n][i];

代码如下:

#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std ;

const int INF=0xfffffff ;               //这是int型最大值

int m,n;                            //mn

int value[105][105],dp[105][105],d[105][105][105];

int max(int x,int y){return x>y?x:y;}      //求最大值

int main()

{

    int T,i,j,k;

   while(scanf("%d",&T)!=EOF)

       {

              int count=0;

              while(T--)

              {

                     for(i=0;i<105 ;i++)

                            for(j=0;j<105 ;j++)

                                   dp[i][j]=-INF;          //初始化记忆搜索数组为int最小值

                     scanf("%d%d",&m,&n);

                     for(i=0;i<m ;i++)

                            for(j=0;j<n ;j++)

                                   scanf("%d",&value[i][j]);

               if(n==1)                     //如果只有一列,直接输出

                  {

                         printf("Case#%d:\n%d\n",++count,value[0][0]);

                         continue ;

                     }

            //d数组的初始化

                  memset(d,0,sizeof(d)) ;

                     for(i=0;i<n ;i++)

                  {

                         for(j=0 ;j<m ;j++)

                            {

                                   for(k=0;k<=j ;k++)

                                   {

                                          if(j==k)

                                                 d[j][i][k]=value[j][i];

                                          else

                                          {

                                                 d[j][i][k]=d[j-1][i][k]+value[j][i] ;

                                                 d[k][i][j]=d[j][i][k];

                                          }

                                   }

                            }

                     }

            //开始动态规划记忆搜索

                     dp[0][1]=value[0][0];

                     for(i=1;i<m ;i++)

                            dp[i][1]=dp[i-1][1]+value[i][0];

                     for(i=2;i<n ;i++)

                     {

                            for(j=0;j<m ;j++)

                            {

                                   for(k=0;k<m ;k++)

                                   {

                                          dp[j][i]=max(dp[j][i],dp[k][i-1]+d[k][i-1][j]);

                                   }

                            }

                     }

                     intans=-INF;

                     for(i=0;i<m ;i++)

                     {

                            inttemp=dp[i][n-1]+d[0][n-1][i] ;

                            ans=max(ans,temp);

                     }

                     printf("Case#%d:\n%d\n",++count,ans) ;

              }

    }

    return 0 ;

}

                                                 

这样解决完毕时间复杂度是O(n^3),n最大是100,所以这样做不会超时。

这篇关于百度之星第四题(记忆化搜索)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1093659

相关文章

百度/小米/滴滴/京东,中台架构比较

小米中台建设实践 01 小米的三大中台建设:业务+数据+技术 业务中台--从业务说起 在中台建设中,需要规范化的服务接口、一致整合化的数据、容器化的技术组件以及弹性的基础设施。并结合业务情况,判定是否真的需要中台。 小米参考了业界优秀的案例包括移动中台、数据中台、业务中台、技术中台等,再结合其业务发展历程及业务现状,整理了中台架构的核心方法论,一是企业如何共享服务,二是如何为业务提供便利。

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

hdu 4517 floyd+记忆化搜索

题意: 有n(100)个景点,m(1000)条路,时间限制为t(300),起点s,终点e。 访问每个景点需要时间cost_i,每个景点的访问价值为value_i。 点与点之间行走需要花费的时间为g[ i ] [ j ] 。注意点间可能有多条边。 走到一个点时可以选择访问或者不访问,并且当前点的访问价值应该严格大于前一个访问的点。 现在求,从起点出发,到达终点,在时间限制内,能得到的最大

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

hdu4277搜索

给你n个有长度的线段,问如果用上所有的线段来拼1个三角形,最多能拼出多少种不同的? import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;

项目实战系列三: 家居购项目 第四部分

购物车 🌳购物车🍆显示购物车🍆更改商品数量🍆清空购物车&&删除商品 🌳生成订单 🌳购物车 需求分析 1.会员登陆后, 可以添加家居到购物车 2.完成购物车的设计和实现 3.每添加一个家居,购物车的数量+1, 并显示 程序框架图 1.新建src/com/zzw/furns/entity/CartItem.java, CartItem-家居项模型 /***

浙大数据结构:04-树7 二叉搜索树的操作集

这道题答案都在PPT上,所以先学会再写的话并不难。 1、BinTree Insert( BinTree BST, ElementType X ) 递归实现,小就进左子树,大就进右子树。 为空就新建结点插入。 BinTree Insert( BinTree BST, ElementType X ){if(!BST){BST=(BinTree)malloc(sizeof(struct TNo

【python计算机视觉编程——7.图像搜索】

python计算机视觉编程——7.图像搜索 7.图像搜索7.1 基于内容的图像检索(CBIR)从文本挖掘中获取灵感——矢量空间模型(BOW表示模型)7.2 视觉单词**思想****特征提取**: 创建词汇7.3 图像索引7.3.1 建立数据库7.3.2 添加图像 7.4 在数据库中搜索图像7.4.1 利用索引获取获选图像7.4.2 用一幅图像进行查询7.4.3 确定对比基准并绘制结果 7.

JS中【记忆函数】内容详解与应用

在 JavaScript 中,记忆函数(Memoization)是一种优化技术,旨在通过存储函数的调用结果,避免重复计算以提高性能。它非常适用于纯函数(同样的输入总是产生同样的输出),特别是在需要大量重复计算的场景中。为了彻底理解 JavaScript 中的记忆函数,本文将从其原理、实现方式、应用场景及优化方法等多个方面详细讨论。 一、记忆函数的基本原理 记忆化是一种缓存策略,主要用于函数式编