poj1088&&hdu1078(不用记忆化搜索)

1.poj1088

链接:点击打开链接

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

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
    int x,y,val;
    friend bool operator<(node a,node b){
        return a.val>b.val;
    }
}s[205*205];
int G[205][205],dp[205][205];
int main(){
    int i,j,n,m,xx,yy,id,ans;
    while(scanf("%d%d",&n,&m)!=EOF){
        for(i=0;i<n;i++)
        for(j=0;j<m;j++){
            scanf("%d",&G[i][j]);
            id=i*m+j;
            s[id].x=i;
            s[id].y=j;
            s[id].val=G[i][j];
        }                                       //记录每个位置和高度
        sort(s,s+n*m);                          //问题的关键在于高度低的状态一定是
        memset(dp,0,sizeof(dp));                //由高度高的状态推出来的,因此按高度
        for(i=0;i<n*m;i++){                     //进行排序
            xx=s[i].x,yy=s[i].y;
            if(xx!=0&&G[xx][yy]<G[xx-1][yy])
            dp[xx][yy]=max(dp[xx][yy],dp[xx-1][yy]+1);
            if(xx!=n-1&&G[xx][yy]<G[xx+1][yy])
            dp[xx][yy]=max(dp[xx][yy],dp[xx+1][yy]+1);
            if(yy!=0&&G[xx][yy]<G[xx][yy-1])
            dp[xx][yy]=max(dp[xx][yy],dp[xx][yy-1]+1);
            if(yy!=m-1&&G[xx][yy]<G[xx][yy+1])
            dp[xx][yy]=max(dp[xx][yy],dp[xx][yy+1]+1);
        }                                       //特殊判断边界
        ans=0;
        for(i=0;i<n;i++)
        for(j=0;j<m;j++)
        ans=max(ans,dp[i][j]);
        printf("%d\n",ans+1);
    }
    return 0;
}


 

2.hdu1078

链接:点击打开链接

题意:给出n*n的矩阵,每个格子里面有食物的数量,问一只老鼠每次走最多k步所能吃到的最多的食物,每一次只能有直线并且下一次吃的食物一定比当前吃的食物多

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
    int x,y,val;
    friend bool operator<(node a,node b){
        return a.val<b.val;
    }
}s[105*105];
int G[105][105],dp[105][105];
int main(){
    int n,i,j,k,id,xx,yy,nx,ny,ans;
    while(scanf("%d%d",&n,&k)!=EOF){
        if(n==-1&&k==-1)
        break;
        for(i=1;i<=n;i++)
        for(j=1;j<=n;j++){
            scanf("%d",&G[i][j]);
            id=(i-1)*n+j;
            s[id].x=i;
            s[id].y=j;
            s[id].val=G[i][j];
        }
        memset(dp,0,sizeof(dp));
        dp[1][1]=G[1][1];
        sort(s+1,s+n*n+1);                      //这类题都是一样,只要知道状态是如何转移   
        for(i=1;i<=n*n;i++){                    //然后排序即可
            nx=s[i].x,ny=s[i].y;
            if(dp[nx][ny])
            for(j=-k;j<=k;j++){
                if(j==0)
                continue;
                xx=nx+j;
                yy=ny+j;
                if(xx>=1&&xx<=n&&G[xx][ny]>G[nx][ny])
                dp[xx][ny]=max(dp[xx][ny],dp[nx][ny]+G[xx][ny]);
                if(yy>=1&&yy<=n&&G[nx][yy]>G[nx][ny])
                dp[nx][yy]=max(dp[nx][yy],dp[nx][ny]+G[nx][yy]);
            }
        }
        ans=0;
        for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
        ans=max(ans,dp[i][j]);
        printf("%d\n",ans);
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值