• Codeforces Round #174 (Div. 1) B. Cow Program(动态规划+记忆化搜索)


    题目大意

    Farmer John 给了他的 cows 一个程序玩。这个程序有两个整形变量 x 和 y,并且在一个正数序列 a1 a2 a3,...,an (2≤n≤2*105,1≤ai≤109)中执行以下操作:

            1、初始化 x=1, y=0,如果经过任何步骤之后 x≤0 或者 x>n,程序立刻停止运行

            2、x 和 y 同时增加 ax(注意:增加的值是 a 序列中的第 x 个,也就是 ax

            3、x 减小 ax,y 增加 ax

            4、程序重复执行步骤 2 和步骤 3 直至终止

    现在给了你 a2 a3 a4,...,an,程序总共运行了 n-1 次,第 i(1≤i≤n-1) 次运行的时候 a1=i,问程序停止运行之后 y 是多少?如果不能停止运行,输出 -1

    做法分析

    观察步骤 2 和步骤 3,可以知道:

            1、y 是记录的 x 变化的值,程序终止只和 x 有关,与 y 无关

            2、步骤 2 使得 x 增加,步骤 3 使得 x 减小

            3、当 x 为 1 的时候,下一步必然是执行步骤 2(因为上面的第 2 条规律),永远不可能停止,输出 -1

            4、当 x 表示的值重复出现并且下一步执行的步骤相同时,程序必然陷入一个循环中,永远不可能停止,输出 -1

    想到了上面的四个规律,这道题目就简单了

    定义 f(i, j) 表示:当 x=i 的时候,到程序终止,y 会加上的值是多少,那么,状态就是这样转移的:

            f(i, 0)=f(i+ai, 1)+ai:这一步该执行步骤 2

            f(i, 1)=f(i-ai, 0)+ai:这一步该执行步骤 3

    在计算的过程中,如果 i+ai 或者 i-ai 超过范围,必然是程序终止了;如果 i=1 或者 i 是之前某个经过的节点,必然陷入死循环

    那么每次 a1 变化的时候,直接输出 a1+f(1+a1, 1) 就行了 

    参考代码

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 
     5 using namespace std;
     6 
     7 typedef long long LL;
     8 const int N=200006;
     9 const LL INF=((1LL)<<60);
    10 
    11 LL f[N][2];
    12 bool vs[N][2];
    13 int n, A[N];
    14 
    15 LL DP(int x, int dir)
    16 {
    17     if(x>n || x<=0) return 0;
    18     if(x==1) return INF;
    19     if(f[x][dir]!=-1) return f[x][dir];
    20     if(vs[x][dir]) return INF;
    21     vs[x][dir]=1;
    22     LL res;
    23     if(dir==0) res=DP(x+A[x], 1);
    24     else res=DP(x-A[x], 0);
    25     if(res!=INF) f[x][dir]=(LL)A[x]+res;
    26     else f[x][dir]=INF;
    27     return f[x][dir];
    28 }
    29 
    30 int main()
    31 {
    32     scanf("%d", &n);
    33     for(int i=2; i<=n; i++) scanf("%d", &A[i]);
    34     memset(f, -1, sizeof f);
    35     memset(vs, 0, sizeof vs);
    36     for(int i=2; i<=n; i++)
    37     {
    38         if(f[i][0]==-1) f[i][0]=DP(i, 0);
    39         if(f[i][1]==-1) f[i][1]=DP(i, 1);
    40     }
    41     for(int i=1; i<n; i++)
    42     {
    43         if(f[1+i][1]==INF) printf("-1\n");
    44         else printf("%I64d\n", i+f[1+i][1]);
    45     }
    46     return 0;
    47 }
    B. Cow Program

    题目链接 & AC通道

    Codeforces Round #174 (Div. 1) B. Cow Program

  • 相关阅读:
    关于debug和release 以及new 和delete
    关于new 和delete
    构造函数为什么不能是虚函数
    大端小端【转载】
    “error LNK1169: 找到一个或多个多重定义的符号”的解决方法(转载)
    memset memcpy函数
    漫谈递归
    scanf 和cin 的区别
    enum枚举类型 的用法
    关于浮点数和字面值常量 的使用—— 学习汇编的重要性
  • 原文地址:https://www.cnblogs.com/zhj5chengfeng/p/3082443.html
Copyright © 2020-2023  润新知