滚动数组~\(≧▽≦)/~

今天第一次用了滚动数组,缘由要从一道题说起:POJ 1159 Palindrome

题意:给你一个字符串,求对字符串最少添加几个字符可变为回文串。

分析: 简单做法是直接对它和它的逆序串求最长公共子序列长度len。n-len即为所求。至于为什么,小盆友们可以自己模拟一下下。O(∩_∩)O~因为这不是我们今天讲的重点~噶呜

很明显这是一道LCS题,如果你还不知道什么是LCS,可以点击  LCS  ,我们都知道要开辟一个dp[5001][5001]的数组来存LCS值,问题来了,当我开心的交上代码的时候竟然

内存超限了~!!看了下讨论组,说改成short int 能过,果然过了,但是memory==49156.。。太大了。上网一搜,发现了滚动数组这个东西,memory立即编程188K。啥都不说了,进入正题!

滚动数组的作用在于优化空间,主要应用在递推或动态规划中(如01背包问题)。因为DP题目是一个自底向上的扩展过程,我们常常需要用到的是连续的解,前面的解往往可以

舍去。所以用滚动数组优化是很有效的。利用滚动数组的话在N很大的情况下可以达到压缩存储的作用。

一个DP,如果需要1000×1000的空间,其实根据DP的无后效性,可以开成2×1000,然后通过滚动,获得和1000×1000一样的效果。

滚动数组常用于DP之中,在DP过程中,我们在由一个状态转向另一个状态时,很可能之前存储的某些状态信息就已经无用了,例如在01背包问题中,从理解角度讲我们应开

DP[i][j]的二维数组,第一维我们存处理到第几个物品,也就是阶段了,第二维存储容量,但是我们获得DP[i],只需使用DP[i - 1]的信息,DP[i - k],k>1都成了无用空间,因此我们

可以将数组开成一维就行,迭代更新数组中内容,滚动数组也是这个原理,目的也一样,不过这时候的问题常常是不可能缩成一维的了,比如一个DP[i][j]需要由DP[i - 1 ][k],

DP[i - 2][k]决定,i<n,0<k<=10;n <=100000000;显然缩不成一维,正常我们应该开一个DP[100000005][11]的数组,结果很明显,超内存,其实我们只要开DP[3][11]

就够了DP[i%3][j]由DP[(i - 1)%3][k]和DP[(i - 2)%3][k]决定,空间复杂度差别巨大。

学以致用:http://poj.org/problem?id=1159 小盆友们快去做一做吧~噶呜~

滚动数组~\(≧▽≦)/~

时间: 2024-10-08 01:02:56

滚动数组~\(≧▽≦)/~的相关文章

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); 如果直接

[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);

【滚动数组】【状压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

HDU 1024 Max Sum Plus Plus --- dp+滚动数组

HDU 1024 题目大意:给定m和n以及n个数,求n个数的m个连续子系列的最大值,要求子序列不想交. 解题思路:<1>动态规划,定义状态dp[i][j]表示序列前j个数的i段子序列的值,其中第i个子序列包括a[j], 则max(dp[m][k]),m<=k<=n 即为所求的结果 <2>初始状态: dp[i][0] = 0, dp[0][j] = 0; <3>状态转移: 决策:a[j]自己成为一个子段,还是接在前面一个子段的后面 方程: a[j]直接接在前面

hdu 1864 实数离散化+动态规划+滚动数组

#include <cstdio> #include <iostream> #include <algorithm> #include <queue> #include <cmath> #include <cstring> #include <stack> #include <set> #include <map> #include <vector> using namespace st

HDU 3392 Pie(DP+滚动数组)

题意:有一些男生女生,男生女生数量差不超过100 ,男生女生两两配对.要求求出一种配对方法,使每一对的高度差的和最小. 思路:(我是真的笨笨笨!!磨磨唧唧写一堆是因为我笨!我看了别人的博客,思路全是学别人的,轻喷!)设人少的一组人数为n,b[],人多的一组人数为m,g[](b[],g[]先排好序),用dp[i][j]表示n中的前i个人与m中的前j个人配对所得到的最小值. 那么dp[i][j]就是min(dp[i-1][k]+|b[i]-g[k]|),就是n中前i-1个人和m中前1~k个人配对的最

poj3624 01背包入门 dp+滚动数组

poj3624 01背包 dp+滚动数组 Charm Bracelet Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 25458   Accepted: 11455 Description Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the bes

滚动数组 (定义和用法)

滚动数组的作用在于优化空间,主要应用在递推或动态规划中(如01背包问题).因为DP题目是一个自底向上的扩展过程,我们常常需要用到的是连续的解,前面的解往往可以舍去.所以用滚动数组优化是很有效的.利用滚动数组的话在N很大的情况下可以达到压缩存储的作用. 一个简单的例子: 斐波那契数列: 一般代码: #include<iostream> #include<cstdio> using namespace std; int Fib[25]; int fib(int n) { Fib[0]