zoukankan      html  css  js  c++  java
  • HDU 4374 One hundred layer(单调队列DP)

      题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=116242#problem/E 

      题意:差不多就是男人勇下百层的游戏。从第一层到最后一层最多能够拿到多少分数。每层里面最多可以左右平移T个单位,同时从那个地方到下一层。一开始在第一层的X处。

      首先要了解什么是单调队列,这里推荐一个博客写的很不错,直接引用了:http://blog.csdn.net/justmeh/article/details/5844650 

      用dp(i,j)表示在第i层的第j个位置所能得到的最多的分数,然后这题就可以在每一层用单调队列进行双向维护dp(i,j)的值了。

      具体见代码:

     1 #include <stdio.h>
     2 #include <algorithm>
     3 #include <string.h>
     4 #include <queue>
     5 using namespace std;
     6 
     7 int dp[100+5][10000+5];
     8 int num[100+5][10000+5];
     9 int n,m,x,t;
    10 
    11 struct node
    12 {
    13     int id,val;
    14     node (int id=0,int val=0):id(id),val(val){}
    15 };
    16 void solve()
    17 {
    18     for(int i=0;i<=10000+4;i++) dp[0][i]=-0x3f3f3f3f;
    19     dp[0][x]=0;
    20     for(int i=1;i<=n;i++)
    21     {
    22         deque<node> Q;
    23         for(int j=1;j<=m;j++)
    24         {
    25             int tem=dp[i-1][j]-num[i][j-1]; //从j出开始计算和的话,是减掉其前一个的
    26             while(!Q.empty()&&tem>Q.back().val) Q.pop_back();
    27             Q.push_back(node(j,tem));
    28             while(!Q.empty()&&j-Q.front().id>t) Q.pop_front();
    29             dp[i][j]=Q.front().val+num[i][j];
    30         }
    31         while(!Q.empty()) Q.pop_back();
    32         for(int j=m;j>=1;j--)
    33         {
    34             int tem=dp[i-1][j]+num[i][j]; //逆向维护和正向的次序相反
    35             while(!Q.empty()&&tem>Q.back().val) Q.pop_back();
    36             Q.push_back(node(j,tem));
    37             while(!Q.empty()&&Q.front().id-j>t) Q.pop_front();
    38             dp[i][j]=max(dp[i][j],Q.front().val-num[i][j-1]);
    39         }
    40     }
    41     int ans=dp[n][1];
    42     for(int i=2;i<=m;i++) ans=max(ans,dp[n][i]);
    43     printf("%d
    ",ans);
    44 }
    45 
    46 int main()
    47 {
    48     while(scanf("%d%d%d%d",&n,&m,&x,&t)==4)
    49     {
    50         for(int i=1;i<=n;i++)
    51             for(int j=1;j<=m;j++)
    52             {
    53                 scanf("%d",&num[i][j]);
    54                 num[i][j]+=num[i][j-1];
    55             }
    56         solve();
    57     }
    58     return 0;
    59 }

      思路倒是简单,但是被莫名其妙的坑了很久。。因为对于上面结构体里面的构造方法,写(node)(j,tem)是错误的!正确写法是node(j,tem)。因为以前使用{node}(j,tem)的写法有时候会CE,所以换了这种写法,找了很长时间的错误。。另外,在下面用tem变量时一开始用的是t,忘记和全局变量的t重复了。。悲剧啊QAQ。。。

  • 相关阅读:
    670. Maximum Swap
    653. Two Sum IV
    639. Decode Ways II
    636. Exclusive Time of Functions
    621. Task Scheduler
    572. Subtree of Another Tree
    554. Brick Wall
    543. Diameter of Binary Tree
    535. Encode and Decode TinyURL
    博客园自定义背景图片
  • 原文地址:https://www.cnblogs.com/zzyDS/p/5495703.html
Copyright © 2011-2022 走看看