Labyrinth

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

Problem Description
度度熊是一只喜欢探险的熊,一次偶然落进了一个m*n矩阵的迷宫,该迷宫只能从矩阵左上角第一个方格开始走,只有走到右上角的第一个格子才算走出迷宫,每一次只能走一格,且只能向上向下向右走以前没有走过的格子,每一个格子中都有一些金币(或正或负,有可能遇到强盗拦路抢劫,度度熊身上金币可以为负,需要给强盗写欠条),度度熊刚开始时身上金币数为0,问度度熊走出迷宫时候身上最多有多少金币?
 
Input
输入的第一行是一个整数T(T < 200),表示共有T组数据。
每组数据的第一行输入两个正整数m,n(m<=100,n<=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

 
  DP题
  一开始用DFS做的,果断超时。看讨论版才发现需要用DP,当时就蔫了,后来还是查了网上的题解,才明白怎么用DP解这道题,对DP的理解更深了。下面是思路:
  思路:这道题的思路是一列列的确定每一个格子的最大金币数。先确定第一列的最大金币数,因为只能向下走,所以很好求。之后每一列每格的最大金币数可以由前一列求得。
  例如要求dp[i][j](dp[][]的含义是走到这个位置的最大金币数),则从前一列有3种走法到这个格子:
  1、它的左边一个格子,即a[i][j-1],直接向右走一个格子;
  、a[i][j-1]上面的所有格子,可以先向右走一个格,然后向下一直走到a[i][j]的位置;
  、a[i][j-1]下面的所有格子,可以先向右走一个格,然后向上一直走到a[i][j]的位置。
  遍历上述所有路径的过程中需要记录一个最大值,最后这个值就是dp[i][j]的值。
  由此可知,确定该位置的每一种路径,需要遍历m次。而你需要确定每一列的每一个格子的dp[][]值,所以这个算法的时间复杂度为O(n*m*m)
  代码
 #include <iostream>
#include <stdio.h>
using namespace std;
#define inf 0x7fffffff
int a[][];
int dp[][]; //记录走到某一位置的金币最大值
int m,n;
void DP()
{
int i,j,k;
dp[][] = a[][];
for(i=;i<=m;i++) //初始化第一列
dp[i][] = dp[i-][] + a[i][];
for(i=;i<=n;i++){ //每一列 a[][i]
for(j=;j<=m;j++){ //每一列的每一个位置 a[j][i]
//有三种路径到达这个位置。
//1.它左边的位置直接向右走过来。
//2.它左边的位置的上面所有位置向右再一直向下走到这个位置。
//3.它左边的位置的下面所有位置向右再一直向上走到这个位置。
//不断比较,在这个位置处 dp[j][i] 记录以上3条路径的最大值。即为走到这个位置的能拥有的最大金币数。
//这是以 a[j][i] 为重心考虑,遍历到达 a[j][i]的三种路径,求出最大值
int t = dp[j][i-] + a[j][i];
if(t>dp[j][i])
dp[j][i] = t;
for(k=j-;k>=;k--){
//a[k][i-1] --> a[j][i]这个位置所拥有的金币数
t = t-dp[k+][i-]+dp[k][i-]+a[k][i];
if(t>dp[j][i])
dp[j][i] = t;
}
t = dp[j][i-] + a[j][i];
for(k=j+;k<=m;k++){
//a[k][i-1] --> a[j][i]这个位置所拥有的金币数
t = t-dp[k-][i-]+dp[k][i-]+a[k][i];
if(t>dp[j][i])
dp[j][i] = t;
}
}
}
}
int main()
{
int i,j,Case,T;
scanf("%d",&T);
for(Case=;Case<=T;Case++){
scanf("%d%d",&m,&n);
for(i=;i<=m;i++) //输入迷宫,初始化dp[][]
for(j=;j<=n;j++){
scanf("%d",&a[i][j]);
dp[i][j] = -inf;
}
printf("Case #%d:\n",Case);
DP();
printf("%d\n",dp[][n]);
}
return ;
}

  贴上超时的DFS代码

 #include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int Max;
int a[][];
bool isv[][];
int dx[] = {,-,};
int dy[] = {,,};
int m,n;
bool judge(int x,int y)
{
if(x< || x>m || y< || y>n)
return true;
if(isv[x][y])
return true;
return false;
}
void dfs(int x,int y,int money)
{
if(x== && y==n){
if(money>Max)
Max=money;
}
int i;
for(i=;i<;i++){
int nx = x+dx[i];
int ny = y+dy[i];
if(judge(nx,ny))
continue;
//可以走
isv[nx][ny] = true;
dfs(nx,ny,money+a[nx][ny]);
isv[nx][ny] = false;
}
}
int main()
{
int i,j,Case,T;
scanf("%d",&T);
for(Case=;Case<=T;Case++){
scanf("%d%d",&m,&n);
for(i=;i<=m;i++)
for(j=;j<=n;j++)
scanf("%d",&a[i][j]);
printf("Case #%d:\n",Case);
Max=;
memset(isv,,sizeof(isv));
isv[][] = true;
dfs(,,a[][]);
printf("%d\n",Max);
}
return ;
}

2014百度之星资格赛 1004:Labyrinth(DP)的更多相关文章

  1. 2014 百度之星 题解 1004 Labyrinth

    Problem Description 度度熊是一仅仅喜欢探险的熊,一次偶然落进了一个m*n矩阵的迷宫,该迷宫仅仅能从矩阵左上角第一个方格開始走,仅仅有走到右上角的第一个格子才算走出迷宫,每一次仅仅能 ...

  2. 2014百度之星资格赛——Disk Schedule

    2014百度拥有明星格比赛--Disk Schedule Problem Description 有非常多从磁盘读取数据的需求,包含顺序读取.随机读取. 为了提高效率.须要人为安排磁盘读取. 然而.在 ...

  3. 百度之星资格赛 1004 度度熊的午饭时光(01背包+最小序号和+字典序+有bug)

    分析 首先声明一下,我的代码有漏洞的,求大神给个正确代码 思路如下: 首先做一遍01背包记录路径并求出最大总分,令path[i][j]表示第i个物品包含在dp[j]的求值过程中.再逆序枚举money, ...

  4. 2014百度之星资格赛 1001:Energy Conversion(水题,逻辑题)

    Energy Conversion Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  5. ACM学习历程—BestCoder 2015百度之星资格赛1004 放盘子(策略 && 计算几何)

    Problem Description 小度熊喜欢恶作剧.今天他向来访者们提出一个恶俗的游戏.他和来访者们轮流往一个正多边形内放盘子.最后放盘子的是获胜者,会赢得失败者的一个吻.玩了两次以后,小度熊发 ...

  6. 2014百度之星资格赛—— Xor Sum(01字典树)

    Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Total ...

  7. 2017百度之星资格赛 1003:度度熊与邪恶大魔王(DP)

    .navbar-nav > li.active > a { background-image: none; background-color: #058; } .navbar-invers ...

  8. ACM-百度之星资格赛之Labyrinth——hdu4826

    Labyrinth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  9. HDU 5686:2016"百度之星" - 资格赛 Problem B

    原文链接:https://www.dreamwings.cn/hdu5686/2645.html Problem B Time Limit: 2000/1000 MS (Java/Others)    ...

随机推荐

  1. backbone调试

    有一个谷歌的扩展程序:https://chrome.google.com/webstore/detail/backbone-debugger/bhljhndlimiafopmmhjlgfpnnchjj ...

  2. 2016 Multi-university training contest

    day 1 A 给G,w(e)1M(diff),|V|100K,|E|1M,求 MST MST上任意两点间距离的期望 显然MST唯一 E(dis(u,v))可以通过计算每条边的贡献加出来 B n个并行 ...

  3. 【GoLang】并发小结

    006.并发 1 概念 1.1 goroutine是Go并行设计的核心,goroutine的本质是轻量级线程 1.2 golang的runtime实现了对轻量级线程即goroutine的智能调度管理 ...

  4. 【GoLang】深入理解slice len cap什么算法? 参数传递有啥蹊跷?

    先上结论 .内置append函数在现有数组的长度 < 时 cap 增长是翻倍的,再往上的增长率则是 1.25,至于为何后面会说. .Go语言中channel,slice,map这三种类型的实现机 ...

  5. Qt 使用sqlserver

    1. pro 添加 QT       +=sql 2. void MainWindow::connectSqlServer() { QSettings *setIni = new QSettings( ...

  6. 整数划分问题-解法汇总(暂有DP-递归)

    整数划分问题是一个锻炼组合数学,递归以及动态规划很好的例子,虽然问题看似简单,但是其中玄机万千,有人转化成为背包问题,有人用生成函数解,有人以此作为企业面试题目,可见这种问题的认可度还是很高的. 整数 ...

  7. 理解和解决MySQL乱码问题【转】

    本文来自:http://www.cnblogs.com/cenalulu/p/4325693.html 要了解为什么会出现乱码,我们就先要了解从客户端发起请求,到MySQL存储数据,再到下次从表取回客 ...

  8. zookeeper windows 入门安装和测试

    一.序言       以下是我对zookeeper 的一些理解:       zookeeper 作为一个服务注册信息存储的管理工具,好吧,这样说得很抽象,我们举个“栗子”. 栗子1号: 假设我是一家 ...

  9. Android studio 自定义打包APK名称

    Android Studio打包应用默认生成的apk名称是:app-release.apk .如果我们要让生成的apk名跟我们版本包名有联系的话,那我们就要自定义生成的apk名了,要怎么做呢. 我们只 ...

  10. 如何让数据库在每天的某一个时刻自动执行某一个存储过程或者某一个sql语句

    这就要涉及到代理的知识了哦,首先我们要启动代理服务.