pku1088 dfs+dp记忆化搜索

滑雪

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 88861   Accepted: 33344

Description

Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子

 1  2  3  4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。

Input

输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。

Output

输出最长区域的长度。

Sample Input

5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

Sample Output

25

很简单的题目,一遍过,因为题目要求的是从大到小的路径,所以根本就不需要用vist标记已经访问的节点了,这条路本身就是自带有向属性

#include <iostream>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
#include <algorithm>

const int inf = (1<<31)-1;
const int MAXN = 1e2+10;
using namespace std;

int dp[MAXN][MAXN];
int vist[MAXN][MAXN];
int a[MAXN][MAXN];
int n,m;

int mov[4][2]={-1,0,1,0,0,1,0,-1};

int check(int x,int y){
    if(x<1||y<1||x>n||y>m)return 0;
   // if(vist[x][y]==1)return 0;
    else return 1;
}

void dfs(int x,int y){
    int nx,ny;
   // cout<<"haha"<<endl;
    for(int i=0;i<4;i++){
        nx = x+mov[i][0];
        ny = y+mov[i][1];
        if(check(nx,ny)&&a[x][y]>a[nx][ny]){
            if(dp[nx][ny]==1){
               // vist[nx][ny] = 1;
                dfs(nx,ny);
                dp[x][y] = max(dp[x][y],dp[nx][ny]+1);
                //vist[nx][ny] = 0;
            }
            else{
                dp[x][y] = max(dp[x][y],dp[nx][ny]+1);
            }
        }
    }
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF){
        int mmax = -inf;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&a[i][j]);
                dp[i][j] = 1;
                vist[i][j] = 0;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(dp[i][j]!=1||vist[i][j]==0){
                    //if()
                    vist[i][j] = 1;
                    dfs(i,j);
                }
                mmax = max(mmax,dp[i][j]);
            }
        }
        /*for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                printf("%d ",dp[i][j]);
            }
            cout<<endl;
        }*/
        cout<<mmax<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}

时间: 2024-11-17 20:13:53

pku1088 dfs+dp记忆化搜索的相关文章

11782 - Optimal Cut(树形DP+记忆化搜索)

题目链接:11782 - Optimal Cut 题意:按前序遍历给定一棵满二叉树,现在有k次,可以选k个节点,获得他们的权值,有两个条件: 1.一个节点被选了,他的子节点就不能选了. 2.最终选完后,根到所有叶子的路径上,都要有一个被选的节点. 思路:树形dp,dp[u][k]代表在结点u,可以选k个节点,那么就分两种情况 选u节点,dp[u][k] = node[u]; 选子节点之和,那么就把k次分配给左右孩子,dp[u][k] = max(dp[u][k], dp[u][i], dp[u]

[hihocoder 1033]交错和 数位dp/记忆化搜索

#1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0,?a1,?...,?an?-?1,定义交错和函数: f(x)?=?a0?-?a1?+?a2?-?...?+?(?-?1)n?-?1an?-?1 例如: f(3214567)?=?3?-?2?+?1?-?4?+?5?-?6?+?7?=?4 给定 输入 输入数据仅一行包含三个整数,l,?r,?k(0?≤?l?≤?r?≤?1018,?|k|

UVA - 10817 Headmaster&#39;s Headache (状压dp+记忆化搜索)

题意:有M个已聘教师,N个候选老师,S个科目,已知每个老师的雇佣费和可教科目,已聘老师必须雇佣,要求每个科目至少两个老师教的情况下,最少的雇佣费用. 分析: 1.为让雇佣费尽可能少,雇佣的老师应教他所能教的所有科目. 2.已聘老师必须选,候选老师可选可不选. 3.dfs(cur, subject1, subject2)---求出在当前已选cur个老师,有一个老师教的科目状态为 subject1,有两个及以上老师教的科目状态为 subject2的情况下,最少的雇佣费用. dp[cur][subje

poj 1088 动态规划+dfs(记忆化搜索)

滑雪 Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个 区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17 18 19 6

poj1664 dp记忆化搜索

http://poj.org/problem?id=1664 Description 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. Input 第一行是测试数据的数目t(0 <= t <= 20).以下每行均包含二个整数M和N,以空格分开.1<=M,N<=10. Output 对输入的每组数据M和N,用一行输出相应的K. Sample Input 1 7 3 Sample Output 8 /

【DP】树形DP 记忆化搜索

DP中的树形DP,解决方法往往是记忆化搜索.显然,树上递推是很困难的.当然做得时候还是得把状态定义和转移方程写出来:dp[u][1/0]表示以u为根节点的树 涂(1) 或 不涂(0) 颜色的最少方案数.树上DP有两个经典问法:一条边两端至少有个一个端点涂色,问整个tree最少涂色次数:还有一种忘了...此题是前种问法. #include<cstdio> #include<cstring> #include<algorithm> using namespace std;

状压DP+记忆化搜索 UVA 1252 Twenty Questions

题目传送门 1 /* 2 题意:给出一系列的01字符串,问最少要问几个问题(列)能把它们区分出来 3 状态DP+记忆化搜索:dp[s1][s2]表示问题集合为s1.答案对错集合为s2时,还要问几次才能区分出来 4 若和答案(自己拟定)相差小于等于1时,证说明已经能区分了,回溯.否则还要加问题再询问 5 */ 6 /************************************************ 7 * Author :Running_Time 8 * Created Time :

UVa 10817 (状压DP + 记忆化搜索) Headmaster&#39;s Headache

题意: 一共有s(s ≤ 8)门课程,有m个在职教师,n个求职教师. 每个教师有各自的工资要求,还有他能教授的课程,可以是一门或者多门. 要求在职教师不能辞退,问如何录用应聘者,才能使得每门课只少有两个老师教而且使得总工资最少. 分析: 因为s很小,所以可以用状态压缩. dp(i, s1, s2)表示考虑了前i个人,有一个人教的课程的集合为s1,至少有两个人教的集合为s2. 在递归的过程中,还有个参数s0,表示还没有人教的科目的集合. 其中m0, m1, s0, s1, s2的计算用到位运算,还

POJ 4968 DP||记忆化搜索

给出N个人的平局分X 根据GPA规则计算可能的最高平均GPA和最低平均GPA 可以DP预处理出来所有结果  或者记忆化搜索 DP: #include "stdio.h" #include "string.h" int inf=100000000; double a[11][1100],b[11][1100]; double Max(double a,double b) { if (a<b) return b; else return a; } double M