前言:即使是简单的递归,在复杂度过高时也可以使用简单的dp。

一般有两种情况,一是利用dp思想求最优子结构进行搜索剪枝,二是利用搜索进行dp数组的填充。

例题一、hdu1978

题目大意:这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m)。游戏的规则描述如下:

1.机器人一开始在棋盘的起始点并有起始点所标有的能量。

2.机器人只能向右或者向下走,并且每走一步消耗一单位能量。

3.机器人不能在原地停留。

4.当机器人选择了一条可行路径后,当他走到这条路径的终点时,他将只有终点所标记的能量。



如上图,机器人一开始在(1,1)点,并拥有4单位能量,蓝色方块表示他所能到达的点,如果他在这次路径选择中选择的终点是(2,4)

点,当他到达(2,4)点时将拥有1单位的能量,并开始下一次路径选择,直到到达(6,6)点。

我们的问题是机器人有多少种方式从起点走到终点。这可能是一个很大的数,输出的结果对10000取模。

一开始的思路:既然已知迷宫起点终点,果断dfs。

dfs最重要的一点就是明确函数中应有的参数和结束条件

在这里,很显然终止条件是到达右下角的点,所以函数中参数要有x,y坐标。又因为在每个点有对应的能量,由能量决定下一步能走到哪里进行枚举,所以参数还应该包含当前点的能量。

#include <bits/stdc++.h>
using namespace std;
int n,m,a[109][109];
int ans;//答案
bool p(int q,int w)
{
if(q>=0&&q<n&&w>=0&&w<m)
return true;
else
return false;
}
void dfs(int power,int x,int y)
{
if(x==n-1&&y==m-1)
{
ans++;
ans%=10000;
return;
}
for(int i=0;i<=power;i++)
{
if(x+i>=n)
break;
for(int j=0;j<=power-i;j++)
{
if(y+j>=m)
break;
if(i==0&&j==0)
continue;
dfs(a[x+i][y+j],x+i,y+j);
}
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
cin>>a[i][j];
}
dfs(a[0][0],0,0);
cout<<ans;
}
}

很遗憾,完全超时。想来也是,100*100的棋盘还有能量,怎么可能跑得了,仔细一想剪枝也无从下手,因为每一步都是必须要走的。

但是,我们从终点开始看,很显然最后一行的元素只能一直向右走。那我们从最后一行m-1个元素看起,从这里出发只有一种走法,再看第m-2个元素,如果能量大于1,则可以一步走到终点,也可以先走到m-1,那走法就加上dp[n-1][m-1]。

由此一来,状态转移方程就容易得出。使用dfs从最后一行枚举每个点进行dfs,看它能到达哪些点,每到一个点就加上那个点在dp数组中的值,一步一步向前搜索。



蓝色块是起点能到达的格子,走法就是每个格子的dp数和嘛!

代码如下

#include <bits/stdc++.h>
using namespace std;
int n,m,a[209][209],dp[209][209];
int dfs(int power,int x,int y,int k)
{
int sumn=k;
if(dp[x][y]!=0)
return dp[x][y];
for(int i=0;i<=power;i++)
{
if(x+i>=n)//防止越界
break;
for(int j=0;j<=power-i;j++)
{
if(y+j>=m)//防止越界
break;
if(i==0&&j==0)//不能待在原地不懂
continue;
sumn+=dfs(a[x+i][y+j],x+i,y+j,0);
}
}
return sumn;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
cin>>a[i][j];
}
dp[n-1][m-1]=1;dp[n-1][m]=dp[n][m-1]=1;。。初始化
for(int i=n-1;i>=0;i--)
for(int j=m-1;j>=0;j--)
dp[i][j]=dfs(a[i][j],i,j,0)%10000;//dfs就是求当前格子的走法
cout<<dp[0][0]<<endl;
}
}

搜索+简单dp的更多相关文章

  1. hdu2067 简单dp或者记忆化搜索

    题意: 小兔的棋盘 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  2. 简单dp总结

    ### 简单dp总结 本文是阅读<挑战程序设计第二版>其中关于dp章节所作总结.将简要描述dp的部分知识. 一.dp是什么? dp在计算机专业学科中全称是动态规划(dynamic prog ...

  3. HDU 1087 简单dp,求递增子序列使和最大

    Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 ...

  4. Codeforces Round #260 (Div. 1) A. Boredom (简单dp)

    题目链接:http://codeforces.com/problemset/problem/455/A 给你n个数,要是其中取一个大小为x的数,那x+1和x-1都不能取了,问你最后取完最大的和是多少. ...

  5. codeforces Gym 100500H A. Potion of Immortality 简单DP

    Problem H. ICPC QuestTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100500/a ...

  6. 简单dp --- HDU1248寒冰王座

    题目链接 这道题也是简单dp里面的一种经典类型,递推式就是dp[i] = min(dp[i-150], dp[i-200], dp[i-350]) 代码如下: #include<iostream ...

  7. poj2385 简单DP

    J - 简单dp Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:65536KB     64bit ...

  8. hdu1087 简单DP

    I - 简单dp 例题扩展 Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:32768KB     ...

  9. poj 1157 LITTLE SHOP_简单dp

    题意:给你n种花,m个盆,花盆是有顺序的,每种花只能插一个花盘i,下一种花的只能插i<j的花盘,现在给出价值,求最大价值 简单dp #include <iostream> #incl ...

随机推荐

  1. JVM日常排查问题。基本操作和命令

    1.jstat jstat -gcutil pid 5s    //pid进程号 每隔5s监控一次内存回收情况 E 代表 Eden 区使用率:O(Old)代表老年代使用率    :P(Permanen ...

  2. Docker php安装扩展步骤详解

    前言 此篇,主要是演示docker-php-source , docker-php-ext-install ,docker-php-enable-docker-configure 这四个命令到底是用来 ...

  3. 不错的spring学习博客

    http://blog.csdn.net/xyh820/article/details/7303330/

  4. C - Max Sum Plus Plus HDU - 1024

    用二位数组dp[i][j]记录组数为i,前j个数字的最大子段和. 转移方程: dp[i][j],考虑第j个数,第j个数可以并到前面那一组,此时dp[i][j]=dp[i][j-1]+arr[j],第j ...

  5. B. 蚂蚁觅食(二)

    B. 蚂蚁觅食(二) 单点时限: 1.0 sec 内存限制: 512 MB 一只饥饿的小蚂蚁外出觅食,幸运的的小蚂蚁发现了好多食物.但是这些食物位于一个N∗M的方格魔法阵的右下角,而小蚂蚁位于方格法阵 ...

  6. Aria2任意文件写入漏洞

    目录: 简介 漏洞描述 payload 漏洞复现 一.Aria2介绍 Aria2是一个命令行下运行,多协议,多来源下载工具(HTTP / HTTPS,FTP,BitTorrent,Metalink), ...

  7. srt字幕翻译

    需要把字幕名改成i.txt 有有道和谷歌 代码: #Author:Chenglong Qian #Copyright :Chenglong Qian import json import reques ...

  8. pytorch torchversion自带的数据集

    from torchvision.datasets import MNIST # import torchvision # torchvision.datasets. #准备数据集 mnist = M ...

  9. Ubuntu创建WiFi:16.0.4

    点击编辑链接,点击桌面状态栏的网络图标 点击增加 类型选择WiFi 名称.SSID,均要填写,模式选择:热点 wifi安全性:选择一个安全模式,这里选的是, wpa 及 wpa2个人 必须说的是:选择 ...

  10. phpcms模块安装

    工作中需要用到 phpcms开源框架,借鉴了   http://www.cnblogs.com/benpaodelulu/p/6874201.html这个地址,搞定的 ,非常实用 如果有用到的朋友们可 ...