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][dre][j][cur],其中i表示当前遍历的命令的序号,dre表示当前状态乌龟是往左还是往右(初始往右),j表示当前状态还剩多少次操作,cur表示当前状态相对于原点的距离。在dp数组中,由于这四个值确定的话,那么继续搜下去我们得到的结果是一定的,所以可以以此进行记忆化搜索。

其实前面还遗留了一个问题,我们贪心的尽可能的将T转化为F,那么一定会出现T的数目小于操作数的情况。如果遇到这样的情况,我们可以算一下还剩下多少的操作数没有转。因为每步指令可以被修改很多次,那么如果剩下的是偶数,那对结果是没有影响的,如果是奇数,那我们只好将最左边或者最右边的F改为T了(最后算出来的距离减一)。

动态规划的题,一般都有两种写法,一种是直推(for循环),另一种就是写递归函数(dfs),用dp数组实现记忆化搜索。最开始拿到这题的时候呢,我首先想的还是直推,

后来写得有点问题,换成了dfs的写法,利用一个四维数组进行记忆化搜索.

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define N 51
using namespace std;
int dp[N*2][2][N][N*4];
char a[N*2];
int n,len,ans;
int dfs(int idx,int j,int t,int cur)
{
    if(j>n) return 0;
    if(idx==len)
    {
        ans=max(ans,abs(cur)-((n-j)&1));//如果是(n-j)剩下的操作数为奇数,那么减一
        return ans;
    }
    int &res=dp[idx][(t-j)&1][n-j][cur+100];
    if(res!=-1) return res;//记忆化搜索
    if(a[idx]=='F') return res=dfs(idx+1,j,t,cur+(((t-j)&1)?-1:1));//如果是F,那么不转换
    if(a[idx]=='T')
    {
        return res=max(dfs(idx+1,j,t+1,cur),dfs(idx+1,j+1,t+1,cur+(((t-j)&1)?-1:1)));//转换和不转换的情况
    }
}
int main()
{
    memset(dp,-1,sizeof dp);
    scanf("%s",a);
    len=strlen(a);
    scanf("%d",&n);

    dfs(0,0,0,0);
    cout<<ans<<endl;
    return 0;
}

这是比较长一点的代码。。后来为了爬上solution size第一页,我丧心病狂的将代码减到了15行。。。

贴下来纪念一下╰( ̄▽ ̄)╮

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,len,ans,dp[102][2][51][202];char a[102];
int dfs(int idx,int j,int t,int cur){
    if(j>n) return 0;if(!a[idx]) return ans=max(ans,(cur>=0?cur:-cur)-((n-j)&1));
    if(dp[idx][(t-j)&1][n-j][cur+100]!=-1) return dp[idx][(t-j)&1][n-j][cur+100];
    if(a[idx]=='F') return dp[idx][(t-j)&1][n-j][cur+100]=dfs(idx+1,j,t,cur+(((t-j)&1)?-1:1));
    if(a[idx]=='T') return dp[idx][(t-j)&1][n-j][cur+100]=max(dfs(idx+1,j,t+1,cur),dfs(idx+1,j+1,t+1,cur+(((t-j)&1)?-1:1)));
}
int main(){
    memset(dp,-1,sizeof dp);scanf("%s%d",a,&n);dfs(0,0,0,0),printf("%d\n",ans);
    return 0;
}

时间: 2024-11-09 10:36:06

Codeforces 132C. Vasya and Beautiful Arrays【DP,dfs】的相关文章

Codeforces 354C Vasya and Beautiful Arrays[dp+暴力]

题意: 给出n个整数,对每个整数可以减去0-k的任意一个数 求这样操作后,n个数的最大GCD是多少 分析: 我们首先可以知道n个整数中最小的数是多少 而且,最终的答案肯定不大于这个数 这个n个整数中最小的数是答案的上限 然后对于答案的下限 可以肯定的是 1肯定是答案的下限 2呢?3呢?为什么1一定是 其实,0-k+1,都可以作为答案 为什么? 可以把k想象成一个剪刀 对k+1来说,任何数都可以剪掉0-k变成k+1的倍数(任何数模k+1的结果都是0-k) 所以0-k也可以,综上0-k+1都可以,所

codeforces 797 E. Array Queries【dp,暴力】

题目链接:codeforces 797 E. Array Queries   题意:给你一个长度为n的数组a,和q个询问,每次询问为(p,k),相应的把p转换为p+a[p]+k,直到p > n为止,求每次询问要转换的次数. 题解:纯暴力会TLE,所以在k为根号100000范围内dp打表 dp[i][j]表示初始p为i, k为j,需要转换几次可以大于n. 状态转移方程:dp[i][j] = dp[i+a[i]+j] + 1 #include <cstdio> #include <al

【Java,JNI】学习汇总

START FROM 2014/5/12 for memory of wenchuan [1]关于java内存的三篇文章: 1,内存模型http://www.cnblogs.com/aigongsi/archive/2012/04/26/2470296.html 而内存模型就是规定了一个规则,处理器如何同主内存同步数据的一个规则. 2,垃圾回收http://www.cnblogs.com/aigongsi/archive/2012/04/06/2434771.html 要点:jvm采用找root

【oracle11g,18】存储结构:临时表,手工条带化,表/索引迁移表空间,删除表,外部表

一. 临时表 临时表放在临时表空间,不生成redo,只有undo. 在临时表中可以创建索引.视图及触发器,还可以使用"Export and Import(导出和导入)"或"Data Pump(数据泵)"导出和导入临时表的定义.但是,即使使用了ROWS 选项,也不会导出数据. 有基于事务(默认)和基于session两种,其他的会话不能访问到. 在临时表中,DML锁永远不需要. 1.创建默认的(基于事务的)临时表:(on commit delete rows:提交时清空

HDU 1501 Zipper(DP,DFS)

题意  判断能否由字符串a,b中的字符不改变各自的相对顺序组合得到字符串c 本题有两种解法  DP或者DFS 考虑DP  令d[i][j]表示能否有a的前i个字符和b的前j个字符组合得到c的前i+j个字符  值为0或者1  那么有d[i][j]=(d[i-1][j]&&a[i]==c[i+j])||(d[i][j-1]&&b[i]==c[i+j])   a,b的下标都是从1开始的  注意0的初始化 #include<cstdio> #include<cst

mapreduce原理【分区,分组】

分析这个原理,的原因是: 1.更好的理解MAPREDUCE的过程. 2.在二次排序时会用到这个原理,二次排序要重写分区方法,重写分组方法:如果原理没搞明白,就无法写二次排序的代码. Key 默认分区 默认分组 自定义分区 自定义分组 Abc123 1.使用系统默认分区方式,是按KEY进行分区. 2.KEY相同,分划分到一个分区且只能划分到一个分区. 划分方式按KEY的HASHCODE进行计算. 3.假设设定为3个分区,则划分方式可能是 a) 分区1:Abc789,Cde123,Cde456 b)

【你好,windows】嵌入式win8.1 X86X64企业纯净版安装版2019.6.20

1·采用Windows 8.1 专业版cn_windows_embedded_8.1_industry_enterprise_with_update_x86_dvd_6052218.iso和cn_windows_embedded_8.1_industry_enterprise_with_update_x64_dvd_6052153.iso原版制作,打齐到2019年6月13日微软发布的月 累积安全更新补丁KB4503276和远程控制认证漏洞补丁KB4503290(包含勒索补丁kb4012213).

【I&#39;m Telling the Truth】【HDU - 3729】 【匈牙利算法,DFS】

思路 题意:该题主要说几个同学分别说出自己的名次所处区间,最后输出可能存在的未说谎的人数及对应的学生编号,而且要求字典序最大. 思路:刚刚接触匈牙利算法,了解的还不太清楚,附一个专门讲解匈牙利算法的博文,个人认为讲的比较清晰. AC代码 #include<iostream> #include<cstdio> #include<cstring> using namespace std; int T, n; struct Stue { int l, r; }; Stue p

CodeForces - 55D - Beautiful numbers(数位DP,离散化)

链接: https://vjudge.net/problem/CodeForces-55D 题意: Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. We will not argue with