zoukankan      html  css  js  c++  java
  • 【JZOJ1753】锻炼身体

    题目

    题目链接:https://gmoj.net/senior/#main/show/1753
    胖子很有钱。他购买了一个先进的跑步机(真的不一样哦~~~~)。
    这个跑步机是这样的:

    1. 可以把它看成一个N*M的矩阵。有的格子是障碍不能经过(用x表示),有的格子是空地可以经过(用.表示)。
    2. 对于每一个时段,跑步机有不同的倾斜方向。由于胖子太胖了,所以他这个时候只有2种选择:要么沿这个方向移动(每秒移动1个格子),或者艰难的保持在原来的位置不动。
      现在胖子已经设定好了跑步机在不同时段中的倾斜方向。众所周知,保持在原地不动是不会做功的。胖子要减肥就要做功。所以他想知道他最多能够跑多长的路程。

    思路

    (f[k][i][j]) 表示第 (k) 个时段后在 ((i,j)) 的最大路程。
    假设第 (k) 个时刻是向上的,那么 (f[k][i][j]) 可能由 (f[k-1][isim n][j]) 转移而来。注意要判断不能走的格子和这个时刻的时间大小。
    暴力搞是 (O(kn^3)) 的,发现一个点只可以由一段前面固定长度的区间最大值转移而来,直接上单调队列优化即可。
    时间复杂度 (O(kn^2))

    代码

    #include <bits/stdc++.h>
    #define Clear { while(q.size()) q.pop_back(); continue; }
    using namespace std;
    
    const int N=210,Inf=1e9;
    int n,m,sx,sy,t,ans,f[N][N][N];
    char ch[N][N];
    deque<int> q;
    
    struct node
    {
    	int s,t,p;
    }a[N];
    
    bool cmp(node x,node y)
    {
    	return x.s<y.s;
    }
    
    int main()
    {
    	scanf("%d%d%d%d%d",&n,&m,&sx,&sy,&t);
    	for (int i=1;i<=n;i++)
    		scanf("%s",ch[i]+1);
    	for (int i=1;i<=t;i++)
    		scanf("%d%d%d",&a[i].s,&a[i].t,&a[i].p);
    	sort(a+1,a+1+t,cmp);
    	for (int i=2;i<=t;i++)
    		if (a[i].s!=a[i-1].t+1)
    		{
    			a[i].t-=(a[i].s-a[i-1].t-1);
    			a[i].s=a[i-1].t+1;
    		}
    	memset(f,0xcf,sizeof(f));
    	f[0][sx][sy]=0;
    	for (int k=1;k<=t;k++)
    	{
    		int tt=a[k].t-a[k].s+1;
    		if (a[k].p==1)
    		{
    			for (int j=1;j<=m;j++)
    			{
    				while (q.size()) q.pop_back();
    				for (int i=n;i>=1;i--)
    				{
    					if (ch[i][j]=='x') Clear;
    					while (q.size() && q.front()-i>tt) q.pop_front();
    					while (q.size() && f[k-1][q.back()][j]+q.back()<=f[k-1][i][j]+i)
    						q.pop_back();
    					q.push_back(i);
    					if (q.size()) f[k][i][j]=f[k-1][q.front()][j]+q.front()-i;
    				}
    			}
    		}
    		if (a[k].p==2)
    		{
    			for (int j=1;j<=m;j++)
    			{
    				while (q.size()) q.pop_back();
    				for (int i=1;i<=n;i++)
    				{
    					if (ch[i][j]=='x') Clear;
    					while (q.size() && i-q.front()>tt) q.pop_front();
    					while (q.size() && f[k-1][q.back()][j]-q.back()<=f[k-1][i][j]-i)
    						q.pop_back();
    					q.push_back(i);
    					if (q.size()) f[k][i][j]=f[k-1][q.front()][j]+i-q.front();
    				}
    			}
    		}
    		if (a[k].p==3)
    		{
    			for (int i=1;i<=n;i++)
    			{
    				while (q.size()) q.pop_back();
    				for (int j=m;j>=1;j--)
    				{
    					if (ch[i][j]=='x') Clear;
    					while (q.size() && q.front()-j>tt) q.pop_front();
    					while (q.size() && f[k-1][i][q.back()]+q.back()<=f[k-1][i][j]+j)
    						q.pop_back();
    					q.push_back(j);
    					if (q.size()) f[k][i][j]=f[k-1][i][q.front()]+q.front()-j;
    				}
    			}
    		}
    		if (a[k].p==4)
    		{
    			for (int i=1;i<=n;i++)
    			{
    				while (q.size()) q.pop_back();
    				for (int j=1;j<=m;j++)
    				{
    					if (ch[i][j]=='x') Clear;
    					while (q.size() && j-q.front()>tt) q.pop_front();
    					while (q.size() && f[k-1][i][q.back()]-q.back()<=f[k-1][i][j]-j)
    						q.pop_back();
    					q.push_back(j);
    					if (q.size()) f[k][i][j]=f[k-1][i][q.front()]+j-q.front();
    				}
    			}
    		}
    	}
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++)
    			ans=max(ans,f[t][i][j]);
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    ES6中的export,import ,export default
    centos7 安装php 多线程pthreads
    ubuntu系统安装nginx出现的错误(依赖环境没有安装完)
    ubuntu彻底干净卸载MySQL、Apache2、Php的方法(各版本通用
    mysql-ubuntu14.04彻底卸载mysql
    centos 中GTK的安装
    centos 安装cmake 3.3.2
    yum安装方式的php,切换NTS为ZTS版本
    eclipse中jad反编译工具的安装
    在SpringMVC中获取request对象的几种方式
  • 原文地址:https://www.cnblogs.com/stoorz/p/13819730.html
Copyright © 2011-2022 走看看