hdu 4374 One hundred layer

One hundred layer

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1220    Accepted Submission(s): 452


Problem Description
Now there is a game called the new man down 100th floor. The rules of this game is:
   1.  At first you are at the 1st floor. And the floor moves up. Of course you can choose which part you will stay in the first time.
   2.  Every floor is divided into M parts. You can only walk in a direction (left or right). And you can jump to the next floor in any part, however if you are now in part “y”, you can only jump to part “y” in the next floor! (1<=y<=M)
   3.  There are jags on the ceils, so you can only move at most T parts each floor.
   4.  Each part has a score. And the score is the sum of the parts’ score sum you passed by.
Now we want to know after you get the 100th floor, what’s the highest score you can get.
 

Input
The first line of each case has four integer N, M, X, T(1<=N<=100, 1<=M<=10000, 1<=X, T<=M). N indicates the number of layers; M indicates the number of parts. At first you are in the X-th part. You can move at most T parts in every floor in only one direction.
Followed N lines, each line has M integers indicating the score. (-500<=score<=500)
 

Output
Output the highest score you can get.
 

Sample Input
  
  
3 3 2 1 7 8 1 4 5 6 1 2 3
 

Sample Output
  
  
29
 

Source
 

Recommend
zhuyuanchen520
 题目大意:一个n*m的格子。每个格子有对应的分数,每一行只能朝一个方向走,最多走t步然后跳到下一行,问到最后一行后最多能得多少分。
状态转移dp[i][j]表示第到了第i行,起点在j位置,但是还没有开始走的最大值。
从左往右走:dp[i][j]=max(dp[i-1][k]+sum[i-1][j]-sum[i-1][k-1])  (j-k<=t)=max(dp[i-1][k]-sum[i-1][k-1])+sum[i-1][j];
从右往左走:dp[i][j]=max(dp[i-1][k]+sum[i-1][k]-sum[i-1][j-1])  (k-j<=t)=max(dp[i-1][k]+sum[i-1][k])-sum[i-1][j-1]
max中是个待求的值,可以用单调队列维护。max外面是只与j有关的值可以直接求出。
#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define positive(a) ((a)>0?(a):-(a))
using namespace std;
int sum[110][10010];//sum[i][j]存第i行的前j项和
int dp[110][10010];//dp[i][j]表示到第i行的第j部分还没走(不算上该部分的分)的最大值
int n,m,x,t,head,tail;
struct node
{
    int val;
    int id;
} q[10010];
int main()
{
    int i,j,ans;

    while(~scanf("%d%d%d%d",&n,&m,&x,&t))
    {
        memset(sum,0,sizeof sum);
        memset(dp,0xcf,sizeof dp);//初始化为负无穷大
        for(i=1; i<=n; i++)
            for(j=1; j<=m; j++)
            {
                scanf("%d",&sum[i][j]);
                sum[i][j]+=sum[i][j-1];
            }
        dp[1][x]=0;//起点初始为0才能保证答案都是起点走出来的
        for(i=2;i<=n+1;i++)
        {
            head=0;tail=-1;//tail设为-1目的是直接把第一个元素加进去不用比较
            for(j=1;j<=m;j++)//是从上层左边走来的情况
            {
                while(head<=tail&&q[tail].val<dp[i-1][j]-sum[i-1][j-1])
                    tail--;
                q[++tail].val=dp[i-1][j]-sum[i-1][j-1];
                q[tail].id=j;
                while(j-q[head].id>t)
                    head++;
                dp[i][j]=q[head].val+sum[i-1][j];
            }
            head=0;tail=-1;
            for(j=m;j>=1;j--)//从上层右边走来的情况
            {
                while(head<=tail&&q[tail].val<dp[i-1][j]+sum[i-1][j])
                    tail--;
                q[++tail].val=dp[i-1][j]+sum[i-1][j];
                q[tail].id=j;
                while(q[head].id-j>t)
                    head++;
                dp[i][j]=MAX(dp[i][j],q[head].val-sum[i-1][j-1]);
            }
        }
        ans=0xcfcfcfcf;
        for(i=1;i<=m;i++)//由于是是到i层还没走的情况所以要到n+1层去找最大值
            if(dp[n+1][i]>ans)
            ans=dp[n+1][i];
        printf("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值