首页 > 其他分享 >POJ 1088 滑雪 递归+dp | 拓扑排序

POJ 1088 滑雪 递归+dp | 拓扑排序

时间:2023-02-21 19:06:03浏览次数:41  
标签:int max ret 1088 POJ && du dp

从每个点(i,j)向四个方向去看
如果某一个方向(a,b)的数值比当前位置小
先求解(a,b)的最长距离,之后加1即可
朴素的递归重复求解了很多子问题,我们每计算出一个子问题的解,便将他进行存储,这样就可以大大减少时间。

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

int a[101][101];
int dp[101][101];
int R,C;

int findw(int i,int j){
    int ret = 1;
    if( i>=0 && i<R && j>=0 && j<C ){
        if( dp[i][j]>0 ){
            //直接调用子问题的解
            return dp[i][j];
        }
        if( i+1 < R && a[i][j] > a[i+1][j]){
            ret = max(ret,1+findw( i+1,j ) );
        }
        if( i-1 >=0 && a[i][j] > a[i-1][j]){
            ret = max(ret,1+findw( i-1,j ) );
        }
        if( j+1 < C && a[i][j] > a[i][j+1]){
            ret = max(ret,1+findw( i,j+1 ) );
        }
        if( j-1 >= 0 && a[i][j] > a[i][j-1]){
            ret = max(ret,1+ findw( i,j-1 ) );
        }
    }
    //记录子问题的解
    dp[i][j] = ret;
    return ret;
}
int main()
{
    while(scanf("%d%d",&R,&C)!=EOF){
        memset(dp,0,sizeof(dp));
        int ret = -1;
        for(int i=0;i<R;i++){
            for(int j=0;j<C;j++){
                scanf("%d",&a[i][j]);
            }
        }
        for(int i=0;i<R;i++){
            for(int j=0;j<C;j++){
                ret = max(ret, findw(i,j));
            }
        }
        cout<<ret<<endl;
    }
    return 0;
}

POJ 1088 滑雪 递归+dp | 拓扑排序_#include


拓扑排序:

POJ 1088 滑雪 递归+dp | 拓扑排序_ios_02
先将二维数组遍历一遍,每次统计上下左右四个位置中比当前位置(i,j)小的个数,这个为(i,j)的度
将所有度为0的点推入队列

依次从队列取出一个点,
更新该点周围四个点的度,
计算周围四个点的最大路径长度,
记录在dp数组里面

直到队列为空
dp中的最大值就是最后的答案
但不是最后一个出队的时候产生最大值!

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>

using namespace std;

#define debug(x) cout<<#x<<": "<<x<<endl;

int a[101][101];
int dp[101][101];
int du[101][101];
int R,C;

struct point{
    int x;
    int y;
    point():x(0),y(0){}
    point(int x,int y):x(x),y(y){}
};

int solve(){
    int ret = 0;
    queue<point> qu;
    for(int i=0;i<R;i++){
        for(int j=0;j<C;j++){

            if( i+1 < R && a[i][j] > a[i+1][j]){
                du[i][j]++;
            }
            if( i-1 >=0 && a[i][j] > a[i-1][j]){
                du[i][j]++;
            }
            if( j+1 < C && a[i][j] > a[i][j+1]){
                du[i][j]++;
            }
            if( j-1 >= 0 && a[i][j] > a[i][j-1]){
                du[i][j]++;
            }
            if( du[i][j] ==0 ){
                qu.push( point(i,j) );
            }
        }
    }
    /*
    for(int i=0;i<R;i++){
        for(int j=0;j<C;j++){
          cout<<du[i][j]<<" ";
        }
        cout<<endl;
    }
    */
    while( !qu.empty() ){
        //debug(qu.size())
        point p = qu.front();
        qu.pop();
        int i = p.x;
        int j = p.y;

        if( i+1 < R && a[i][j] < a[i+1][j]){
            dp[i+1][j] = max(dp[i+1][j] ,1 + dp[i][j]) ;
            ret = max(ret,dp[i+1][j]);

            du[i+1][j]--;
            if(du[i+1][j]==0){
                qu.push(point(i+1,j));
            }
        }



        if( i-1 >=0 && a[i][j] < a[i-1][j]){
            dp[i-1][j] = max(dp[i-1][j] ,1 + dp[i][j]) ;
            ret = max(ret,dp[i-1][j]);
            du[i-1][j]--;
            if(du[i-1][j]==0){
                qu.push(point(i-1,j));
            }
        }


        if( j+1 < C && a[i][j] < a[i][j+1]){
            dp[i][j+1] = max(dp[i][j+1] ,1 + dp[i][j]) ;
            ret = max(ret,dp[i][j+1]);
            du[i][j+1]--;
            if(du[i][j+1]==0){
                qu.push(point(i,j+1));
            }
        }


        if( j-1 >= 0 && a[i][j] < a[i][j-1]){
            dp[i][j-1] = max(dp[i][j-1] ,1 + dp[i][j]) ;
            ret = max(ret,dp[i][j-1]);
            du[i][j-1]--;
            if(du[i][j-1]==0){
                qu.push(point(i,j-1));
            }
        }


    }
    return ret+1;

}

int main()
{
    while(scanf("%d%d",&R,&C)!=EOF){
        if(R==0 || C==0){
            cout<<0<<endl;
            continue;
        }
        memset(dp,0,sizeof(dp));
        memset(du,0,sizeof(du));

        for(int i=0;i<R;i++){
            for(int j=0;j<C;j++){
                scanf("%d",&a[i][j]);
            }
        }
        int ret = solve();
        cout<<ret<<endl;
    }
    return 0;
}

POJ 1088 滑雪 递归+dp | 拓扑排序_递归_03

标签:int,max,ret,1088,POJ,&&,du,dp
From: https://blog.51cto.com/liyunhao/6077016

相关文章

  • POJ 1636 Prison rearrangement 二部图连通分量+背包
    以第三组为例,我们根据输入可以得到这个二部图根据不能放在一起的情况可以得到这样的连通分量对于每一个连通分量,我们将这个连通分量按照监狱分为两个部分这两个部分调整的......
  • POJ 2228 Naptime 环形DP
    先不考虑环的情况dp[i][j][0]:前i个时间间隔中,已经花费了j个间隔,取得的最大值,并且第i个间隔在休息dp[i][j][1]:前i个时间间隔中,已经花费了j个间隔,取得的最大值,并且第i个间......
  • P2602 [ZJOI2010] 数字计数:数位DP
    https://www.luogu.com.cn/problem/P2602//#include<iostream>//#include<iomanip>//#include<unistd.h>//#include<climits>//#include<string>//#inclu......
  • TCP与UDP简述
    什么是TCPTCP(TransmissionControlProtocol传输控制协议)是一种面向连接的,可靠的,基于字节流的传输通信协议。1、tcp(TransmissionControlProtocol传输控制协议)2、传......
  • BZOJ 4145 [AMPPZ2014]The Prices (状压DP)
    题意你要购买商店,你到第i家商店的路费为,在第家商店购买第种物品的费用为,求最小总费用。分析很容易定义出状态,表示到第行,买的物品情况为的最小费用。按照往常的套路是转移时......
  • [SPOJ] DIVCNT2 - Counting Divisors (square) (平方的约数个数前缀和 容斥 卡常)
    题目vjudgeURL:​​CountingDivisors(square)​​​Letbethenumberofpositivedivisorsof.Forexample,,and.LetGiven,find.InputFirstlinecontains......
  • [oeasy]python0089_大型机的衰落_Dec小型机崛起_PDP_VAX网络
    编码进化回忆上次内容上次回顾了计算机存储单位的演变最小的读写单位是bit8-bit固定下来成为了字节(Byte)位数容量8-bit1Byte1024Byte......
  • Atcoder Educational DP Contest
    序言dp的水平太......
  • UDP 和 TCP? 区别? 应用场景?
    一、UDPUDP(UserDatagramProtocol),用户数据包协议,是一个简单的面向数据报的通信协议,即对应用层交下来的报文,不合并,不拆分,只是在其上面加上首部后就交给了下面的网络层也......
  • ThreadPool线程池工具类
    packagecom.rc.openapi.util;importcom.google.common.util.concurrent.ThreadFactoryBuilder;importjava.util.concurrent.*;publicclassThreadPoolService{/**......