• BZOJ1802 [Ahoi2009]checker [思维题, 动态规划]


    checkerchecker

    题目描述见链接 .


    color{red}{正解部分}

    可以发现当有 22 个连续的红格子出现时, 可以通过这两个红格子将棋子送达每个位置 .

    于是先讨论有 22 个连续红格子的情况, 此时第一问的答案显然为 00 .
    再考虑第二问的答案是什么, 可以预处理出 F[i]F[i] 表示在 ii 位置放置棋子的最小代价,
    ii 位置是红格子时, F[i]=1F[i] = 1, 否则初值 F[i]=infF[i] = inf,
    转移 F[i]=min(F[i],F[i1]+F[i2],F[i+1]+F[i+2])F[i] = min(F[i], F[i-1]+F[i-2], F[i+1]+F[i+2]),
    最后把偶数位的答案累计起来即可 .

    再讨论没有 22 个连续红格子的情况, 此时第一问答案显然为偶数位的白格子个数, 第二问答案为偶数位红格子个数 .

    总时间复杂度 O(N)O(N) .


    color{red}{实现部分}

    • 注意第一个格子即使是红色的, 也要看成白色, 因为不会在第一个格子上放棋子 .
    #include<bits/stdc++.h>
    #define reg register
    typedef long long ll;
    
    const int maxn = 1005;
    const ll inf = 0x3f3f3f3f3f3f3f3f;
    
    int N;
    int flag;
    
    int A[maxn];
    
    ll Ans_1;
    ll Ans_2;
    ll F[maxn];
    
    int main(){
            scanf("%d", &N);
            memset(F, 0x3f, sizeof F);
            for(reg int i = 1; i <= N; i ++){
                    scanf("%d", &A[i]); F[i] = A[i]?1:inf;
                    if(i >= 3 && A[i] && A[i-1]) flag = 1;
            }
            F[1] = inf;
            if(!flag){
                    for(reg int i = 2; i <= N; i += 2)
                            if(A[i]) Ans_2 ++; else Ans_1 ++;
            }else{
                    F[0] = inf, F[N+1] = inf;
                    for(reg int i = 1; i <= N; i ++) if(i != 1) F[i] = std::min(F[i], F[i-1]+F[i-2]);
                    for(reg int i = N; i >= 1; i --) if(i != N) F[i] = std::min(F[i], F[i+1]+F[i+2]);
                    for(reg int i = 2; i <= N; i += 2) Ans_2 += F[i];
                    Ans_1 = 0;
            } 
            printf("%lld
    %lld
    ", Ans_1, Ans_2);
            return 0;
    }
    
  • 相关阅读:
    HttpWebRequest后台读取网页类
    MD5加密方法
    Base64封装类
    3DES封装类
    C#操作XML类
    XML_Qt_资料
    XML_CPP_资料
    h.264_javascript_资料
    ffmpeg_资料_01
    QWebEngineView_简单例子_01
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822499.html
Copyright © 2020-2023  润新知