您的位置:首页 > 其它

单调队列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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: