单调队列HDU 4374 One hundred layer
2016-05-20 19:40
513 查看
题意:在n层每层m个房间的地图中,走过每个房间都可以获得一定的money,但是每层只可以经过t个房间,可以从一个房间直接掉到下一层的同一位置的那个房间,给出x为起始位置。
对于任意一个点可能有两种到达方法一种是直接从上面掉下来,另一种是从旁边过来。
正在学队友的代码风格所以可能整体有点错乱:
#include<bits/stdc++.h>
using namespace std;
#define MAXN 110
#define MAXM 10000+100
int n,m,x,t;
int maps[MAXN][MAXM];
int dp[MAXN][MAXM];
void solve(){
for(int i = 0 ; i <= MAXM ; i ++)
dp[0][i]=-0x7f7f7f7f;//设定最小值,在进行单调队列时可以把非初始位置的点开始的运动排除
dp[0][x] = 0;//开始位置的上层设定为0
for(int i = 1; i <=n ; i++){
deque<pair<int,int> >dq;
for(int j = 1 ;j <=m ;j++){
int tmp = dp[i-1][j]-maps[i][j-1];//直接从上层掉下来可以获得两个房间的money
while(!dq.empty() && tmp>dq.back().second)
dq.pop_back();//如果这个money要多于单调队列的最小值,删除单调队列中的小值,并把这个money入列
dq.push_back(make_pair(j,tmp));
while(!dq.empty()&&j-(dq.front().first)>t)//如果这个点和单调队列的最大值是远到够不到的关系,那么最大值就没有用啦,出列出列
dq.pop_front();
dp[i][j]=dq.front().second+maps[i][j];//在这个点上就有最大值是够得到的最大值
}//直接掉下来的情况
while(!dq.empty())
dq.pop_back();//把单调队列的所有值都删掉进行另一种情况的分析
for(int j=m;j>=1;j--){
int tmp=dp[i-1][j] + maps[i][j];//从旁边过来,因为预处理的关系,所以默认是从左边过来的
while(!dq.empty() && tmp > dq.back().second)
dq.pop_back();
dq.push_back(make_pair(j,tmp));
while(!dq.empty()&&(dq.front().first)-j>t)
dq.pop_front();
dp[i][j]=max(dp[i][j],dq.front().second-maps[i][j-1]);
}//从旁边那个掉下来之后从左边走过来的情况
}
int ans=dp
[1];
for(int i=2; i<=m; i++){
ans=max(ans, dp
[i]);
}
printf("%d\n", ans);
return ;
}
int main(){
while(scanf("%d%d%d%d",&n,&m,&x,&t) != EOF){
memset(maps, 0, sizeof(maps));
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
scanf("%d", &maps[i][j]);
maps[i][j]+=maps[i][j-1];
}
}
solve();
}
return 0;
}
对于任意一个点可能有两种到达方法一种是直接从上面掉下来,另一种是从旁边过来。
正在学队友的代码风格所以可能整体有点错乱:
#include<bits/stdc++.h>
using namespace std;
#define MAXN 110
#define MAXM 10000+100
int n,m,x,t;
int maps[MAXN][MAXM];
int dp[MAXN][MAXM];
void solve(){
for(int i = 0 ; i <= MAXM ; i ++)
dp[0][i]=-0x7f7f7f7f;//设定最小值,在进行单调队列时可以把非初始位置的点开始的运动排除
dp[0][x] = 0;//开始位置的上层设定为0
for(int i = 1; i <=n ; i++){
deque<pair<int,int> >dq;
for(int j = 1 ;j <=m ;j++){
int tmp = dp[i-1][j]-maps[i][j-1];//直接从上层掉下来可以获得两个房间的money
while(!dq.empty() && tmp>dq.back().second)
dq.pop_back();//如果这个money要多于单调队列的最小值,删除单调队列中的小值,并把这个money入列
dq.push_back(make_pair(j,tmp));
while(!dq.empty()&&j-(dq.front().first)>t)//如果这个点和单调队列的最大值是远到够不到的关系,那么最大值就没有用啦,出列出列
dq.pop_front();
dp[i][j]=dq.front().second+maps[i][j];//在这个点上就有最大值是够得到的最大值
}//直接掉下来的情况
while(!dq.empty())
dq.pop_back();//把单调队列的所有值都删掉进行另一种情况的分析
for(int j=m;j>=1;j--){
int tmp=dp[i-1][j] + maps[i][j];//从旁边过来,因为预处理的关系,所以默认是从左边过来的
while(!dq.empty() && tmp > dq.back().second)
dq.pop_back();
dq.push_back(make_pair(j,tmp));
while(!dq.empty()&&(dq.front().first)-j>t)
dq.pop_front();
dp[i][j]=max(dp[i][j],dq.front().second-maps[i][j-1]);
}//从旁边那个掉下来之后从左边走过来的情况
}
int ans=dp
[1];
for(int i=2; i<=m; i++){
ans=max(ans, dp
[i]);
}
printf("%d\n", ans);
return ;
}
int main(){
while(scanf("%d%d%d%d",&n,&m,&x,&t) != EOF){
memset(maps, 0, sizeof(maps));
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
scanf("%d", &maps[i][j]);
maps[i][j]+=maps[i][j-1];
}
}
solve();
}
return 0;
}
相关文章推荐
- CharSet
- WEB手动漏洞挖掘-SQL盲注(DVWA实战)
- Cell复用原理
- 解决Intellij IDEA 控制台中文乱码的问题
- SHELL中计算时间差方法
- MySQL入门--数据表的创建、显示指定数据库中的所有数据表
- 如何优雅地使用 Stack Overflow?
- error MSB3073: :VCEnd”已退出,代码为 1 error MSB3073: :copy............
- 多个线程访问同一个类里面的静态成员变量
- wordpress教程:检测当前页面使用的哪个模板文件的方法
- 十天冲刺开发第二天个人工作总结
- Java高级之类结构的认识
- clog,cout,cerr 输出机制
- Java高级之类结构的认识
- xcode快捷键
- Android之ListView使用方法-SimpleAdapter-两个TextView
- mysqlli
- python
- 自己写的 线段树 的板子
- MVC入门——经典MVC登录实例详解--附完整代码