codeforces 132C Logo Turtle(dp)

可以用三维dp来保存状态, dp[i][j][k]表示在前i个字符变换了j步之后方向为k(k = 1 or k = 0)的最优解,也就是离原点的最大距离。这里规定0方向为正方向,1位负方向,表示的是当前这个人朝哪个方向。这两个方向是对立的。

所以就可以递推一个关系式,分第i个字符为‘F‘ or ‘T‘时

如果为‘F‘

  依次枚举在第i个位置变换了几步,这是枚举的范围为0~j, 假设变换了k步(和上面的dp[i][j][k]当中的k不是一个)

    1. 如果当k为奇数的时候,就是相当于变化了1步,所以‘F‘就变成‘T‘了,那么他的方向也因此变化了。所以当前的方向一定和上一步(也就是i - 1时的方向)的方向相反,所以有dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][1]), 同理,dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][0])

    2.如果k为偶数,相当于没有变化,所以还是字符‘F‘,如果是正方向,那么他就可以由上一步继续向正方向走一步,也就是加1, 如果是负方向,相当于往回走一步,距离就减1,递推方程为dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][0] + 1); dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][1] - 1);

如果为‘T‘

  依次枚举在第i个位置变化了几步,范围也是0~j,假设变换k步

    1.如果k为奇数,这时就变化成了‘F‘,所以dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][0] + 1); dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][1] - 1)

    2.如果k为偶数,这时还是‘T‘,所以dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][1]); dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][0])

其中还有一个问题就是和刚开始的方向的无关,不用管朝哪个方向,只要走的最远的就行了,而且始终有两个相互对立的方向。初始化的时候dp[0][0][0]和dp[0][0][1]都得初始化0,这样才可以往哪走都可以

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 110;
int dp[maxn][maxn][2];
const int inf = 0x3f3f3f3f;
int main()
{
    //freopen("in.txt", "r", stdin);
    char cmd[maxn];
    scanf("%s", cmd + 1);
    int n;
    scanf("%d", &n);
    int len = strlen(cmd + 1);
    //memset(dp, -inf, sizeof(dp));
    for (int i = 0; i <= len; i++)
        for (int j = 0; j <= n; j++) dp[i][j][0] = dp[i][j][1] = -inf;
    dp[0][0][0] = 0;//正方向
    dp[0][0][1] = 0;//负方向,两边都可以走
    for (int i = 1; i <= len; i++)
    {
        for (int j = 0; j <= n; j++)
        {
            for (int k = 0; k <= j; k++)
            {
                if (cmd[i] == ‘F‘)
                {
                    if (k & 1)
                    {
                        dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][1]);
                        dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][0]);
                    }
                    else
                    {
                        dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][0] + 1);
                        dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][1] - 1);
                    }
                }
                else
                {

                    if (k & 1)
                    {
                        dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][0] + 1);
                        dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][1] - 1);
                    }
                    else
                    {
                        dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k][1]);
                        dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k][0]);
                    }
                }
            }

        }

    }
    printf("%d\n", max(dp[len][n][0], dp[len][n][1]));
    return 0;
}

 

时间: 2024-10-05 05:55:01

codeforces 132C Logo Turtle(dp)的相关文章

CodeForces 18E Flag 2 dp

题目链接:点击打开链接 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #include<math.h> #include<queue> #include<string> #include<stdlib.h> #include<a

Codeforces 41D Pawn 简单dp

题目链接:点击打开链接 给定n*m 的矩阵 常数k 下面一个n*m的矩阵,每个位置由 0-9的一个整数表示 问: 从最后一行开始向上走到第一行使得路径上的和 % (k+1) == 0 每个格子只能向或走一步 求:最大的路径和 最后一行的哪个位置作为起点 从下到上的路径 思路: 简单dp #include <cstdio> #include <algorithm> #include<iostream> #include<string.h> #include &

CodeForces 19B Checkout Assistant dp

题目链接:点击打开链接 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <iostream> #include <map> #include <set> #include <math.h> using namespace std; #define inf 115292150460684697

Neko and Aki&#39;s Prank CodeForces - 1152D (括号序列,dp)

大意: 将所有长度为2*n的合法括号序列建成一颗trie树, 求trie树上选出一个最大不相交的边集, 输出边集大小. 最大边集数一定不超过奇数层结点数. 这个上界可以通过从底层贪心达到, 所以就转化为求奇数层结点数. 然后就dp求出前$i$为'('比')'多j个的方案数, 奇数层且合法的时候统计一下贡献即可. #include <iostream> #include <iostream> #include <algorithm> #include <cstdio

codeforces 148D 【概率dp】

题目链接: codeforces 148D Bag of mice 题意:一个包里面有w只白老鼠和b只黑老鼠,公主与龙依次从包中拿老鼠,每次取一只,当龙拿时还会从包中溜走一只,先拿到老鼠的获胜,当背包中没老鼠时且之前没人拿到白老鼠则龙获胜,问公主获胜的概率是多少. 题解: 设dp[i][j]为背包中有i只白老鼠j只黑老鼠时公主获胜的概率 则公主获胜的情况分成三种: 1.直接拿到白老鼠 p1=i/(i+j) 2.公主拿到黑老鼠,龙拿到黑老鼠,逃跑一只黑老鼠 p2=(j/(i+j)) ((j-1)/

[Codeforces 1295F]Good Contest(DP+组合数学)

[Codeforces 1295F]Good Contest(DP+组合数学) 题面 有一个长度为\(n\)的整数序列,第\(i\)个数的值在\([l_i,r_i]\)中随机产生.问这个序列是一个不上升序列的概率(模\(998244353\)意义下). \(n \leq 50,l_i,r_i \leq 998244351\) 分析 和[APIO2016]划艇几乎一模一样.可惜比赛的时候时间不够. 首先把问题转化成求最长不上升序列的数量. 我们把这些区间离散化,分割成两两之间不互相覆盖的若干个区间

三维递推dp Logo Turtle CodeForces - 132C

https://vjudge.net/problem/CodeForces-132C 题意:   F表示向前走,T表示向后转,有N次修改字符的机会,问最多能走多远 思路:dp[ i ][ j ][ d ]表示前i个字符修改了j次,走了k长度,当前朝向是d的状态的最大长度 所以就可以递推一个关系式,分第i个字符为‘F‘ or ‘T‘时 然后多维递推dp就是当前 i.j都是由 老i.j递推出来的,即 i-1,j-k,其实就是记忆化暴力. 注意:要用max就得先全部初始化为-inf,然后dp[0][0

Codeforces 132C. Vasya and Beautiful Arrays【DP,dfs】

题目大意: 在一根数轴上有一只机器龟,它能够听从人们给它的指令做出向前走一步(F)和向后转(T)的操作.给出初始操作,你最开始有修改n步指令的权利(每一个指令可以被修改很多次),问在你修改n次之后,海龟离原点的最大距离. 做法: 很直观的想法,尽可能的将T转化为F,也算是一种贪心的做法吧. 我们用dfs(i,j,t,cur),其中i表示当前遍历的命令的序号,j表示从0~i过程中我转换了多少个T,t表示从0~i的序号中总共出现了多少次T,cur表示当前相对于原点的距离(有正有负),dp[i][dr

Educational Codeforces Round 26 D dp,思维

Educational Codeforces Round 26 D. Round Subset 题意:有 n 个数,从中选出 k 个数,要使这 k 个数的乘积末尾的 0 的数量最多. tags:dp好题 dp[i][j][l] 表示前 i 个数,选取了其中 j 个数,分解因子后有 l 个 5时,最多有多少个 2 .i 这一维明显可以省略. 这题一开始有个地方写挫了..选取 j 个数时,应该反着来,即 for( j, k, 1) ,不是 for( j, 1, k) ,不然会多算. #include