bzoj1499 [NOI2005]瑰丽华尔兹(luoguP2254)(dp+单调队列)
来源:互联网 发布:python 迭代器 编辑:程序博客网 时间:2024/06/06 03:28
题目链接
分析:
样例图:
设计状态f[i][j][k]:表示时间k,正好到(i,j)
知道了刚刚走完的是哪一段,我们就知道了刚才的方向
魔法不限制使用次数,而且不能改变方向(这就很好了嘛)
我们倒着推回去,这样就可以知道上一段时间结束后,我们在哪里了
这样的复杂度是O(nmT)
为了练码力,我专门写了一下这个部分分(50%),发现还是有很多细节的:
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int zz[4][2]={{-1,0},{1,0},{0,-1},{0,1}};int f[201][201][201];struct node{ int s,t,z;};node ti[40003];int n,m,x,y,T;bool mp[201][201];int fan(int x){ if (x==0) return 1; if (x==1) return 0; if (x==2) return 3; if (x==3) return 2;}void doit(){ int i,j,k,tt; memset(f,128,sizeof(f)); f[x][y][1]=0; int ff=1; for (i=ti[1].s;i<=ti[1].t;i++) { int xx=x+i*zz[ti[1].z][0]; int yy=y+i*zz[ti[1].z][1]; if (mp[xx][yy]&&xx>0&&yy>0&&xx<=n&&yy<=m) f[xx][yy][1]=i; else break; } for (k=2;k<=T;k++) for (i=1;i<=n;i++) for (j=1;j<=m;j++) if (mp[i][j]) for (tt=ti[k].s;tt<=ti[k].t;tt++) { f[i][j][k]=max(f[i][j][k-1],f[i][j][k]); //直接继承 int t=tt-ti[k].s+1; int xx=i+t*zz[fan(ti[k].z)][0]; int yy=j+t*zz[fan(ti[k].z)][1]; if (mp[xx][yy]&&xx>0&&yy>0&&xx<=n&&yy<=m) f[i][j][k]=max(f[i][j][k],f[xx][yy][k-1]+t); else break; }}int main(){ scanf("%d%d%d%d%d",&n,&m,&x,&y,&T); char s[201]; for (int i=1;i<=n;i++) { scanf("%s",&s); for (int j=0;j<m;j++) if (s[j]=='x') mp[i][j+1]=0; else mp[i][j+1]=1; } for (int i=1;i<=T;i++) scanf("%d%d%d",&ti[i].s,&ti[i].t,&ti[i].z),ti[i].z--; doit(); int ans=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) ans=max(ans,f[i][j][T]); printf("%d\n",ans); return 0;}
言归正传,显然我们需要优化
由于钢琴的移动方向是在一段时间内是相同的,因此可以考虑成段dp
令f[t][i][j]表示第t段时间时,钢琴位于(i,j)处时,从第1段时间到第t段时间的最长滑行路程
f[t][i][j]=max{f[t−1][i′][j′]+dist{(i′,j′),(i,j)}}
我们考虑用单调队列优化(然而第一人是怎么想用单调队列的就不得而知了)
队尾出队条件
设队尾为(x,y),新插入的点为(x’,y’)
当 dis((x,y),(x′,y′)) <= f[x′][y′]-f[x][y] 时,(x,y)可被删掉
直到dis((x,y),(x′,y′)) > f[x′][y′]-f[x][y],我们再把f[x][y]塞到队列里
队首出队条件
队首是转移点,很简单:只要转移点和当前点的距离大于作用时间,我们就出队
在向上和向下移动的时候,转移发生在一列中,所以我们先枚举列
在向左和向右移动的时候,转移发生在一行中,所以我们先枚举行
每次(也就是每一行,每一列以及出现障碍)转移的时候,我们都需要一个新的队列
而且f[i][j][k]只与上一段时间有关,我们可以用两个二维数组(而不是200*200*200的大数组)来实现
//这里写代码片#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int zz[4][2]={{-1,0},{1,0},{0,-1},{0,1}};int f[201][201],g[201][201];int n,m,x,y,T,tou,wei;bool mp[201][201];struct node{ int x,y;};node Q[201];int dis(node a,node b) {return abs(a.x-b.x)+abs(a.y-b.y);}void insert(node a){ while (tou<wei&&dis(Q[wei],a)<=f[a.x][a.y]-f[Q[wei].x][Q[wei].y]) wei--; Q[++wei]=a;}int get(node a,int l){ while (tou<wei&&dis(a,Q[tou+1])>l) tou++; //距离超过作用时间 if (tou==wei) return 0xefefefef; return f[Q[tou+1].x][Q[tou+1].y]+dis(Q[tou+1],a);}void U(int l){ for (int j=1;j<=m;j++) { tou=wei=0; for (int i=n;i>=1;i--) if (mp[i][j]) { node t; t.x=i;t.y=j; g[i][j]=max(f[i][j],get(t,l)); insert(t); } else tou=wei=0; //有障碍了 } memcpy(f,g,sizeof(f));}void D(int l){ for (int j=1;j<=m;j++) { tou=wei=0; for (int i=1;i<=n;i++) if (mp[i][j]) { node t; t.x=i;t.y=j; g[i][j]=max(f[i][j],get(t,l)); insert(t); } else tou=wei=0; } memcpy(f,g,sizeof(f));}void L(int l){ for (int i=1;i<=n;i++) { tou=wei=0; for (int j=m;j>=1;j--) if (mp[i][j]) { node t; t.x=i;t.y=j; g[i][j]=max(f[i][j],get(t,l)); insert(t); } else tou=wei=0; } memcpy(f,g,sizeof(f));}void R(int l){ for (int i=1;i<=n;i++) { tou=wei=0; for (int j=1;j<=m;j++) if (mp[i][j]) { node t; t.x=i;t.y=j; g[i][j]=max(f[i][j],get(t,l)); insert(t); } else tou=wei=0; } memcpy(f,g,sizeof(f));}int main(){ scanf("%d%d%d%d%d",&n,&m,&x,&y,&T); char s[201]; for (int i=1;i<=n;i++) { scanf("%s",&s); for (int j=0;j<m;j++) if (s[j]=='x') mp[i][j+1]=0; else mp[i][j+1]=1; } memset(f,128,sizeof(f)); memset(g,128,sizeof(g)); f[x][y]=0; for (int i=1;i<=T;i++) { int st,ed,z; scanf("%d%d%d",&st,&ed,&z); switch(z) { case 1:U(ed-st+1);break; case 2:D(ed-st+1);break; case 3:L(ed-st+1);break; case 4:R(ed-st+1);break; } } int ans=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) ans=max(ans,f[i][j]); printf("%d\n",ans); return 0;}
阅读全文
0 0
- bzoj1499 [NOI2005]瑰丽华尔兹(luoguP2254)(dp+单调队列)
- 【bzoj1499】[NOI2005]瑰丽华尔兹(dp+单调队列优化)
- bzoj1499 [NOI2005]瑰丽华尔兹 (单调队列优化DP)
- bzoj1499 [NOI2005]瑰丽华尔兹(dp+单调队列)
- zstu3924 [NOI2005]瑰丽华尔兹 (单调队列dp)
- [NOI2005]瑰丽华尔兹 && dp单调队列
- 【DP】【单调队列】【NOI2005】瑰丽华尔兹
- [BZOJ1499][NOI2005]瑰丽华尔兹
- [bzoj1499][NOI2005]瑰丽华尔兹
- BZOJ1499: [NOI2005]瑰丽华尔兹
- bzoj1499: [NOI2005]瑰丽华尔兹
- [BZOJ1499][NOI2005][DP+优化]瑰丽华尔兹
- BZOJ 1499 [NOI2005]瑰丽华尔兹 动态规划(+单调队列)
- NOI2005瑰丽华尔兹-单调队列
- 【noi2005试题】瑰丽华尔兹 单调队列优化DP
- [bzoj1499][NOI2005] 瑰丽华尔兹 代码
- BZOJ 1499 NOI2005 瑰丽华尔兹 单调队列
- [DP 暴力 || ST表 || 单调队列] BZOJ 1499 [NOI2005]瑰丽华尔兹
- PHP MySQL insert
- 值得看的youtube频道
- 人工智能泡妞第一步 · 了解学科
- dubbo
- matlab 批量读取文件夹内所有图片的几种方法
- bzoj1499 [NOI2005]瑰丽华尔兹(luoguP2254)(dp+单调队列)
- 链接与链接脚本
- MySQL练习题student_score
- [2017纪中10-30]Matrix 二分答案+数论
- 15.1.2文件过滤器
- 51Nod-1672-区间交
- Android onTouchEvent的MotionEvent.ACTION_UP不响应
- 深度学习引发的思考和三巨头时代
- JeremyGuo膜你赛 t3 azui