Live Archive 4327 Parade
来源:互联网 发布:淘宝买家秀在哪里设置 编辑:程序博客网 时间:2024/05/18 03:29
题意:某城由n+1个横向路和m+1个竖向路组成,你的任务是从最南边的路走到最北边的路,使得走过的路上高兴值最大,同一条路不能经过两次,也不能从北向南走,另外,每条横向路有一个长度,在每一行的横向路行走的长度不能超过k
简单起见我们可以看成从北边走到南边
首先预处理数组sum[i][j]表示第i行从第1个点到第j个点的高兴值总和
用f[i][j]表示从i-1行往下走一行位于(i且,j)点时得到的最大的高兴值,我们先不考虑长度的限制,那么容易得到以下方程:
f[i][j]=max{f[i-1][k]+sum[i-1][max(j,k)]-sum[i-1][min(j,k)]}
由于sum[i-1][j]是一个相对常量,所以求f[i-1][k]+sum[i-1][k]的最大值(或求f[i-1][k]-sum[i-1][k]的最大值)要用到单调队列
那么有长度限制该怎么办呢?我们可以再预处理两个数组l[i],r[i]
l[i][j]表示在第i排从第j号点开始向左走能到达的最远的点(即这两个点之间的路的长度和<=k)
那么r[i][j]同理
使用g[j]=f[i-1][k]±sum[i-1][k],然后单调队列里记录编号,如果编号小于l[i][j]或者大于r[i][j]就将队首元素弹出
注意最后答案是max{f[n+2][i]}而不是max{f[n+1][i]}想一想为什么
#include<cstdio>#include<iostream>#include<deque>using namespace std;const int maxn=105,maxm=10005,inf=1e9;inline void _read(int &x){ char t=getchar();bool sign=true; while(t<'0'||t>'9') {if(t=='-')sign=false;t=getchar();} for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0'; if(!sign)x=-x;}int n,m,k,sum[maxn][maxm],t[maxn][maxm],g[maxm];int f[maxn][maxm],l[maxn][maxm],r[maxn][maxm];deque<int>q;int main(){while(scanf("%d%d%d",&n,&m,&k)&&(n||m||k)){int i,j,x; for(i=1;i<=n+1;i++) for(j=1;j<=m;j++){ _read(x); sum[i][j+1]=sum[i][j]+x;}for(i=1;i<=n+1;i++) for(j=1;j<=m;j++)_read(t[i][j]); for(i=1;i<=n+1;i++){ int cur=0,id=1; l[i][1]=1,r[i][m+1]=m+1; for(j=2;j<=m+1;j++){ cur+=t[i][j-1]; while(cur>k)cur-=t[i][id++]; l[i][j]=id;}cur=0,id=m;for(j=m;j;j--){cur+=t[i][j];while(cur>k)cur-=t[i][id--];r[i][j]=id+1;}} for(i=1;i<=m+1;i++)f[n+1][i]=0; for(i=2;i<=n+2;i++){ while(!q.empty())q.pop_back(); for(j=1;j<=m+1;j++){ g[j]=f[i-1][j]-sum[i-1][j]; while(!q.empty()&&q.front()<l[i-1][j])q.pop_front(); while(!q.empty()&&g[j]>=g[q.back()])q.pop_back(); q.push_back(j); f[i][j]=max(f[i-1][j],sum[i-1][j]+g[q.front()]);}while(!q.empty())q.pop_back();for(j=m+1;j;j--){g[j]=f[i-1][j]+sum[i-1][j];while(!q.empty()&&q.front()>r[i-1][j])q.pop_front();while(!q.empty()&&g[j]>=g[q.back()])q.pop_back();q.push_back(j);f[i][j]=max(f[i][j],g[q.front()]-sum[i-1][j]);}}int ans=0;for(i=1;i<=m+1;i++)ans=max(ans,f[n+2][i]); printf("%d\n",ans);}}
0 0
- Live Archive 4327 Parade
- live archive 4212 - Candy
- live archive 4215 - Feynman
- live archive 3708
- Live Archive 2678 Subsequence
- Live Archive 6657
- Live Archive 6655
- Live Archive 3983 Robotruck
- Live Archive 4256 Salesmen
- Live Archive 4253 Archery
- Live Archive 3905 Meteor
- Live Archive 3902 Network
- UVALive 4327 Parade(hdu 2490 Parade)
- live archive 5986 - Wizarding Duel
- Uva-Live Archive-3635-Pie
- Live Archive 6527 Counting ones
- live archive 3713 two-sat
- Live Archive 3029 City Game
- CSS基础教程 -- 媒体查询屏幕适配
- 数组中的逆序对
- LTE资源调度(5)-上行调度请求SR
- Linux新手入门 win7 64位下安装 ubuntukylin双系统的教程(由win7引导ubuntu)
- linux启动_grub及忘记密码怎么办?
- Live Archive 4327 Parade
- CodeForces 621B
- 最简单逻辑迷宫求解
- HDU 5428 The Factor(分解质因子)
- 搭建登录系统的github地址
- 数据结构实验之排序七:选课名单
- html tab标签切换
- Linq连接数据库
- 第十讲angularjs ngSanitize ngRoute ngAnimate 插件