• 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。。。

  • 相关阅读:
    windows查看和杀死占用端口的进程
    jenkins html报告不显示样式
    解决git一直输入用户名和密码的问题
    git中文乱码问题
    java环境变量配置
    web service
    sql 训练及总结
    js 及jQery
    [TYVJ] P1015 公路乘车
    GIT 基本用法
  • 原文地址:https://www.cnblogs.com/zzyDS/p/5495703.html
Copyright © 2020-2023  润新知