【bzoj1499】[NOI2005]瑰丽华尔兹(dp+单调队列优化)
来源:互联网 发布:华为云计算培训 编辑:程序博客网 时间:2024/05/21 02:36
题目:
我是超链接
题解:一个很显然的O(nmT)的做法就是令f[t][i][j]表示时刻t时,钢琴位于(i,j)处时,从时刻1到t的最长滑行路程。很容易得到DP方程
f[t][i][j]=max{f[t−1][i][j],f[t−1][i'][j']+1}
TTTT啦,我们可以用单调队列优化,由于钢琴的移动方向是在一段一段的时间内是相同的,因此可以考虑成段dp。
令f(k,x,y)=此人 k 次滑行后到达(x,y)方格时已经滑行的最长距离。动态规划的状态转移方程如下(以下仅给出向东滑行的状态转移方程,其他 3 个方向上的转移方程可以类似地推出):f(0,startx,starty)=0,f(k,x,y)=max{f(k-1,x,y),f(k-1,x,y-1)+1,f(k-1,x,y-2)+2,......,f(k-1,x,y’)+y-y’}
对于一个具体的例子 k=2,x=1,c2=2可以列出如下等式: f(2,1,1)=max{f(1,1,1)}
f(2,1,2)=max{f(1,1,1)+1,f(1,1,2)} f(2,1,3)=max{f(1,1,1)+2,f(1,1,2)+1,f(1,1,3)}f(2,1,4)=max{f(1,1,2)+2,f(1,1,3)+1,f(1,1,4)}
......
如果我们定义一个序列 a,使得 ai=f(1,1,i)-i+1,则以上等式可以写成: f(2,1,1)=max{a1}=max{a1}
f(2,1,2)=max{a1+1,a2+1}=max{a1,a2}+1f(2,1,3)=max{a1+2,a2+2,a3+2}=max{a1,a2,a3}+2f(2,1,4)=max{a1+3,a2+3,a3+3,a4+3}=max{a2,a3,a4}+3
......
显然,在应用了 a 序列之后,我们就可以只关注 a 序列而不必为每个 ai 加上一个不同的值,从而简化了操作。
首先研究删除操作。很显然,如果队头 a 值的下标对应的方格与当前处理的方格之 间的距离已经大于 ck,则直接将它从队列中删除,即队头指针加一。
接着是插入操作。根据前文中对于队列中元素大小关系的讨论可以得知,插入一个 元素ai 后,队列中不能有元素 aj 满足aj≤ai. 于是,我们可以从队尾开始,依次删除掉不 大于ai 的 a 值,直到队列中剩下的元素都大于 ai. 此时就可以将 ai 插入队尾。
代码:
#include <cstdio>#include <cstring>#include <iostream>#define INF 1e9+7using namespace std;int c[5][2]={{0,0},{-1,0},{1,0},{0,-1},{0,1}};pair <int,int> q[205],tmp;int belong[250],f[205][205],n,m,ans,l,r;int x,y,k,i,j;char st[250][250];bool judge(int x,int y){if (x>=1 && y>=1 && x<=n && y<=m) return true;return false;}void work(int x,int y,int d,int len){l=r=0;for (int i=0;judge(x,y);i++,x+=c[d][0],y+=c[d][1]) if (st[x][y]=='x') l=r=0; else { tmp.first=f[x][y]; tmp.second=i;//崭新程度 while (l<r && q[r-1].first + (i-q[r-1].second)<=tmp.first) r--; q[r++]=tmp; while (l<r && i-q[l].second> len) l++; f[x][y]=q[l].first + i-q[l].second; ans=max(ans,f[x][y]); }}void pts50()//O(n*m*T){int T=0;for (i=1;i<=k;i++){int x,y,fx;scanf("%d%d%d",&x,&y,&fx);T=max(T,y);for (j=x;j<=y;j++) belong[j]=fx; }//f[t][i][j]表示在第tt段时间到达(i,j)最长的距离memset(f,-127,sizeof(f));/*f[0][x][y]=0;for (t=1;t<=T;t++) for (i=1;i<=n;i++) for (j=1;j<=m;j++) if (st[i][j]!='x') f[t][i][j]=max(f[t-1][i][j],f[t-1][i-c[belong[t]][0]][j-c[belong[t]][1]]+1);int ans=0;for (i=1;i<=n;i++) for (j=1;j<=m;j++) ans=max(ans,f[T][i][j]);printf("%d",ans);*/}int main(){scanf("%d%d%d%d%d",&n,&m,&x,&y,&k);for (i=1;i<=n;i++) scanf("%s",st[i]+1);memset(f,0x80,sizeof(f));//一个很小的数字 f[x][y]=0;int len;for (i=1;i<=k;i++){int x,y,fx;scanf("%d%d%d",&x,&y,&fx);len=y-x+1;switch(fx){case 1:for (j=1;j<=m;j++) work(n,j,1,len); break;//留出剩下的n行供于遍历case 2:for (j=1;j<=m;j++) work(1,j,2,len); break;case 3:for (j=1;j<=n;j++) work(j,m,3,len); break;case 4:for (j=1;j<=n;j++) work(j,1,4,len); break;}}printf("%d",ans);}
- 【bzoj1499】[NOI2005]瑰丽华尔兹(dp+单调队列优化)
- bzoj1499 [NOI2005]瑰丽华尔兹 (单调队列优化DP)
- bzoj1499 [NOI2005]瑰丽华尔兹(dp+单调队列)
- bzoj1499 [NOI2005]瑰丽华尔兹(luoguP2254)(dp+单调队列)
- [BZOJ1499][NOI2005][DP+优化]瑰丽华尔兹
- 【noi2005试题】瑰丽华尔兹 单调队列优化DP
- zstu3924 [NOI2005]瑰丽华尔兹 (单调队列dp)
- [NOI2005]瑰丽华尔兹 && dp单调队列
- 【DP】【单调队列】【NOI2005】瑰丽华尔兹
- [BZOJ1499][NOI2005]瑰丽华尔兹
- [bzoj1499][NOI2005]瑰丽华尔兹
- BZOJ1499: [NOI2005]瑰丽华尔兹
- bzoj1499: [NOI2005]瑰丽华尔兹
- NOI2005瑰丽华尔兹-单调队列
- 【NOI2005T1】瑰丽华尔兹-DP单调队列优化
- [bzoj1499][NOI2005] 瑰丽华尔兹 代码
- BZOJ 1499 [NOI2005]瑰丽华尔兹 动态规划(+单调队列)
- BZOJ 1499 NOI2005 瑰丽华尔兹 单调队列
- [题解]bzoj4592 SHOI2015脑洞治疗仪
- allonsy
- Python基础:进程、线程、协程(2)
- 9. Palindrome Number
- [题解]codeforces498d Traffic Jams in the Land
- 【bzoj1499】[NOI2005]瑰丽华尔兹(dp+单调队列优化)
- Java学习第二天
- fairplay密码
- 注解(Annotation)
- String和StringBuffer的不同点
- 九:搭建git服务器
- wifi是否连接且是否能上网
- [题解]POI2015 Kinoman
- 【正一专栏】继续看中国的韬光养晦下盘大棋