奇技淫巧:指针滚动数组

很多人做动归题的时候总是爆空间。虽然这种问题对于竞赛队里面除了我的各种巨佬完全不是问题(开个滚动数组不就得了?),但是因为我实在是太菜了,所以连滚动数组都不会……

不过菜鸡虽然菜,还是要继续生存的,所以菜鸡有菜鸡的办法……

我的灵感来源于计算斐波那契数列的时候:

f[i] = f[i-1]+f[i-2]

这个递推公式。

那么计算第10000个数的时候,我们是不是要把f[9999],f[9998]……f[1]全部保存起来呢?

当然不需要,我们只用记录三个数,然后循环翻过来翻过去更新就行了……(机房众巨佬:这不是傻逼才会问的问题么?)

然后我把它应用到了动归上。

比如说有个动归方程长这样:

f[i][j] = max(f[i][j-1], f[i-1][j], f[i-2][j])

那么其实我们也不需要记录下整个f[][]数组。(机房众巨佬:废话,也许这就是菜鸡吧)

可以发现,f[i][ ]只和f[i-1][ ],f[i-2][ ]有关。

于是只用记录三个一维数组就行了。

但是每次我怎么知道哪个数组存的哪个东西呢?

可以再开一个维,然后每一次把每个数组对应的维更新就行了。

但是其实不用这么麻烦,而且多开一个维还会导致常数变大。

可以开三个指针,然后每一次指针在循环开始的时候指向对应的数组就行了。

……奇技淫巧讲完了。(机房众巨佬:啥?这就是你的干货?)

时间: 2024-12-28 10:34:42

奇技淫巧:指针滚动数组的相关文章

一些常见的优化:读入优化,滚动数组

1.读入优化 我们平时所使用的scanf,cin速度都较慢,当读入的数据达到10^5规模以上时,就会开始显现劣势 而c中自带的getchar函数读入速度较快,可以用来优化数字的读入速度. 1 inline int get_num() 2 { 3 int num = 0; 4 char c; 5 bool flag = false; 6 while ((c = getchar()) == ' ' || c == '\n' || c == '\r'); 7 if (c == '-') flag =

POJ 1159 Palindrome(滚动数组)

链接:click here 题意: 给你一串字符串,让你求最少加入几个字符,才能使得这个字符串是个回文串. 思路: 设a[i]是这个字符串,b[i]是这个字符串的逆序串.那么a[i],b[i]的最长公共子序列就是所求的字符串里拥有的最大的回文串.然后用总串长减去最大的回文串长度即为所求.求最长公共子序列的公式为:dp[i][j]=max(dp[i-1] [j],dp[i][j-1])if(a[i]==b[i])dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1); 如果直接

指针和数组

指针的几个要点: 一 指针的定义,赋值 要区分: int a; int *p = &a; 这是定义的时候初始化,即赋值 ======================= int a; int *p; p = &a; 定义,初始化分开,  就这里我迷惑了好久 ========================== 多个(修饰符)修饰变量,看变量名先和谁结合(先看后缀)(ps:符号和变量之间的空格不要计算,和距离无关 int*和int *....... int * p [5]    先和[ ]结合

C---通过指针访问数组

C语言规定:如果指针变量P已指向数组中的一个元素,则P+1指向同一数组中的下一个元素. 引入指针变量后,就可以用俩种方法来访问数组元素了. 如果p的初值为&a[0],则: P+i 和a+i 就是a[i]的地址,或者说它们指向a数组的第i个元素. *(p+i)或*(a+i)就是p+i或a+i所指向的数组元素,即a[i].例如,*(p+5)或*(a+5)就是a[5]. 指向数组的指针变量也可以带下标,如p[i]与*(p+i)等价. 根据以上叙述,引用一个数组元素可以用: 1.下标法:即用a[i]形式

[CF837D] Round Subset(滚动数组,01背包)

题目链接:http://codeforces.com/contest/837/problem/D 题意:n个数里选k个数,使得它们的乘积末尾0个数最多. 只需要统计每个数的2和5的数量,一个作为容量,一个作为价值.f(i,k,j)表示前i个数选k个,一共有j个2的时候,5最多有几个. 外层枚举前i个数,内层做01背包就可以.但是会MLE,所以滚动数组. 特别注意的是,滚动数组在滚动的时候要拷贝整层,原因是我在更新01背包的时候没有及时复制... 还有f要注意当前层一定要从之前存在的状态更新过来,

【动态规划】【滚动数组】【bitset】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem J. Terminal

有两辆车,容量都为K,有n(10w)个人被划分成m(2k)组,依次上车,每个人上车花一秒.每一组的人都要上同一辆车,一辆车的等待时间是其停留时间*其载的人数,问最小的两辆车的总等待时间. 是f(i,j)表示前i组,j个人是否可行.w(i)表示第i组的人数. if f(i,j)==1 then f(i+1,j+w(i+1))=1. 这是个bitset可以做的事情,每次左移以后或上f(i-1)的bitset即可.其实可以滚动数组. 然后每更新一次bitset,求一下其最左侧的1的位置,就是对于第一辆

【Java】【滚动数组】【动态规划】UVA - 11137 - Ingenuous Cubrency

滚动数组优化自己画一下就明白了. http://blog.csdn.net/u014800748/article/details/45849217 解题思路:本题利用递推关系解决.建立一个多段图,定义状态d(i,j)表示"使用不超过i的整数的立方,累加和为j"的方案数.那么根据加法原理,如果没有选择数字i的立方和就得到了j,那么方案数就是d(i-1,j):如果选择了数字i的立方和才得到了j,那么方案数是d(i,j-i^3).即: d(i,j)=d(i-1,j)+d(i,j-i^3);

指针、数组的理解与关系

一.指针的本质:变量,指针变量就是指针变量int *p:两个变量,一个p(指针变量本身)是int *类型的 另一个是*p(指针指向的那个变量)是int类型的注:指针说白了就是指针类型,前面定义的int类型是为了说明指针指向的那个数的类型,所以指针的解析方式都是按地址来解析的(不管你是char *还是double *,解析方式都是地址)而指向的那个数的类型就要看你怎么定义的了例如:int *aa是按照地址来解析的:*a则是按照int类型来解析的. (1)所有的类型的数据存储在内存中,都是按照二进制

【滚动数组】【状压dp】Gym - 100956F - Colored Path

f(i,j,S)表示到(i,j),且经由的路径上的颜色集合为S的价值的最小值,从上方和左方转移过来即可. 要注意,内存不足,需要滚动数组优化,即使用了map,还是需要. 路径输出的时候,可以再跑一遍dp,这样就不用再开一个大数组了. 我的写法比较菜.卡了常数 #include<cstdio> #include<algorithm> #include<map> using namespace std; int w[401][401],c[401][401]; typede