BZOJ 4884 [Lydsy2017年5月月赛]太空猫(单调DP)

Posted forever97‘s blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 4884 [Lydsy2017年5月月赛]太空猫(单调DP)相关的知识,希望对你有一定的参考价值。

 

【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=4884

 

【题目大意】

  太空猫(SpaceCat)是一款画面精致、玩法有趣的休闲游戏,
  你需要控制一只坐在迷你飞碟上的猫咪在太空里不断探索,让大家看看你能飞得多远。
  游戏地图可以看成一个二维的网格图,上下是两段障碍物。
  在游戏的一开始,太空猫位于地图最左边的下边界之上,且重力方向向下。
  在每个时刻,你可以用手指点击屏幕,翻转重力的方向,
  或者通过遥感控制太空猫往左或往右移动。每次翻转重力方向时,
  你需要消耗的能量值等于上下底边之间的高度差。
  在左右移动的时候,太空猫可以下降到对应重力方向更低的位置,但不能往上爬。
  当然,太空猫也不能穿墙而过。在重力翻转的过程中,
  直到碰到地面之前,你都不能操控太空猫左右移动。
  太空猫的终点位于地图的最右端的下底边之上,
  请计算为了让太空猫到达终点,需要消耗最小能量,如果不能到达请输出-1

 

【题解】

  我们用dp[i][j]表示到第i个位置,重力方向为j时候的最小能量消耗,
  对于不可达要在每个位置特殊判断是否存在c[i]<=f[i-1]或者f[i]>=c[i-1]的情况。

 

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring> 
using namespace std;
typedef long long LL;
const int N=100010;
int n,c[N],f[N];
LL dp[N][2];
const LL INF=0x3f3f3f3f3f3f3f3f;
int main(){
    while(~scanf("%d",&n)){
        for(int i=1;i<=n;i++)scanf("%d",&c[i]);
        for(int i=1;i<=n;i++)scanf("%d",&f[i]);
        memset(dp,0x3f,sizeof(dp));
        dp[1][0]=0; dp[1][1]=c[1]-f[1];
        for(int i=2;i<=n;i++){
            if(f[i]<=f[i-1])dp[i][0]=dp[i-1][0];
            if(c[i]>=c[i-1])dp[i][1]=dp[i-1][1];
            dp[i][0]=min(dp[i][0],dp[i][1]+c[i]-f[i]);
            dp[i][1]=min(dp[i][1],dp[i][0]+c[i]-f[i]);
            if(c[i]<=f[i-1]||f[i]>=c[i-1])dp[i][0]=dp[i][1]=INF;
        }printf("%lld\n",dp[n][0]==INF?-1:dp[n][0]);
    }return 0;
}

以上是关于BZOJ 4884 [Lydsy2017年5月月赛]太空猫(单调DP)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4883[Lydsy2017年5月月赛]棋盘上的守卫 KM算法

[bzoj4883][Lydsy2017年5月月赛]棋盘上的守卫

bzoj4881 [ Lydsy2017年5月月赛 ] -- 二分图染色+线段树

BZOJ 4883 [Lydsy2017年5月月赛]棋盘上的守卫(最小生成环套树森林)

[Bzoj4832][Lydsy2017年4月月赛]抵制克苏恩 (期望dp)

bzoj 4836: [Lydsy2017年4月月赛]二元运算 -- 分治+FFT