随笔分类 - 动态规划
摘要:题意很简单,给定一个N*N的大矩阵,求其中数值和最大的子矩阵。一开始找不到怎么DP,没有最优子结构啊,后来聪哥给了我思路,化成一维,变成最大连续和即可。为了转化成一维,必须枚举子矩阵的宽度,通过预处理的suffix可以很快计算出每一列某一段的和,然后进行一维DP即可。。总复杂度为 O(N^3);#i...
阅读全文
摘要:这个题目蛮有新意的,一度导致我没看透他是区间DP给一个0-L长度的木板,然后给N个数,表示0-L之间的某个刻度,最后要用刀把每个刻度都切一下 使其断开,然后每次分裂的cost是分裂前的木板的长度。求整个分开之后的最小cost。当时下意识就想到类似花瓶插花问题,即dp[i][j],表示第i个事物放在第...
阅读全文
摘要:当初第一次做的是FPLICE这个题,当时就觉得要用图论去搜索,但是当时陷入死思维就是 dp[][]两个维度都是点,这样就违背了题目的本意,题目给定了一个时间T,在不超过时间T的情况下求最小的消耗,这不就是背包嘛。。。即拿T做容量,在图上面 设置 dp[i][j]表示i点的时候 j时间的最小消耗。这样...
阅读全文
摘要:这个题目给定一棵树,以及树的每个树枝的苹果数量,要求在保留K个树枝的情况下最多能保留多少个苹果一看就觉得是个树形DP,然后想出 dp[i][j]来表示第i个节点保留j个树枝的最大苹果数,但是在树形过程中,有点难表示转移后来看了下大神的做法才知道其实可以用背包来模拟 树枝的去留,其实真的是个背包诶,每...
阅读全文
摘要:这是上上次对抗赛的题目了其实现在发现整个代码从头到尾,都是用了背包,怪我们背包没深入学好。比赛的时候,聪哥提出的一种思路是,预处理一下,背包出 ALL攻击 和 single攻击的 血量对应的最小花费,其实这些都没什么问题。。。主要是后面的问题,后面为了找到如何使用ALL攻击是最好的,我们是这样处理的...
阅读全文
摘要:这个题本来有希望在比赛里面出了的当时也想着用递推 因为后面的数明显是由前面的推过来的但是在计算的时候 因为判重的问题 。。。很无语。我打算用一个tot[i]来存i的总种树,tot[i]+=tot[j]//j为可以由j推到i的一系列数,但这样是不对的,会产生大量重复计算。。。看了下标程才发现要用二维来...
阅读全文
摘要:http://acm.whu.edu.cn/land/problem/detail?problem_id=1546这个题目还是聪哥教的方法过的首先搜索是必须的,而且通过搜索来缩点,这些应该要想到,即把图上的起点和终点还有能量点进行标记,之后用bfs找到这些个点的最短路,最多只有12个点,这样对12个点进行状态压缩DP,状态压缩这部分不是很好写用dp[i][j]表示在状态i的情况下,此刻在j点落脚的最大能量数,则先枚举i再枚举j,再枚举k,k代表已经存在于i里面的点 每次从dp[i][k]过度到dp[i][j],从dp[i][k]+dis[k][j]+dis[j][m+1]#include #i
阅读全文
摘要:擦,真不应该让这个题目弄这么久就是一个比较简单的状态DP,先预处理出每一行的可行情况,然后因为当前行是和前两行有关系的,果断不能只用个两维啊,我一开始Dp数组开个两维,只记录当前行的状态,结果在枚举前面行的时候果断就不行啊,因为你枚举了上一行那上一行的前两行又要枚举,果断不行啊,我居然还照着这个思路全部写完并且过了样例,还提交WA了很久都没反应过来至少开三维,dp[i][j][k]记录当前行为j状态,i-1行为k状态时的最大值,那么dp[i][j][k]=max(本身,dp[i-1][k][w]+cot[j]),其中状态和某个状态的含1的个数都预处理好了,j,k,w都是状态编号,w为i-2行的
阅读全文
摘要:昨天是我负责这个题目的,最后没搞出来,真的给队伍拖后腿了。当时都推出来了 我假设最后结果是取了m个物品,则我把这个m个物品按取的先后编号为 k1 k2 k3 k4...km则最终结果就是 (k1.a+k2.a+...km.a)-((m-1)*k1.b+(m-2)*k2.b+....+1*k(m-1).b+0*km.b);由此可见最终的结果必定是从n个石头中选出m个石头,而且这m个石头要按b值的升序来取,因为按上述式子,这m个石头的a值顺序不影响结果,但b值越小的放前面就使得结果越优,这里也算用了一下贪心思想吧,不过是显而易见的。然后当时聪哥就照着这个敲了一个贪心的,WA了。。。之后就肯定了绝对
阅读全文
摘要:这个题目求某个字符串中含的最长的回文子串。就是一个很简单的LCS模型吗,而且我不明白为什么网上这么多人都说仿照某写法把字符串先逆序一下,然后求LCS,我只想问一下,有必要吗?直接按LCS的套路来就行了啊,只不过方式变了下,按上面的写法,又麻烦,又根本没利用的LCS的精髓思想即,先从间隔0位开始做起,然后是间隔1位。。2.。。n-1位,d[i][j]代表i到j的最长回文串个数于是就有 s[i]==s[j] d[i][j]=d[i+1][j-1]+2,否则就取 max(f[i+1][j],f[i][j-1]),不就行啦。还用得着上面那样搞?不过如果这个问题这么简单我也不会放到博客里来写了。主要是下
阅读全文
摘要:这个题目刚看到还真不好下手,把一个是 k的倍数的长度的字符串分成len/k块,每块是k个字母,每个块可以重新组合,最后使得整个序列的相同字母尽量在一起,也就是说,最后会把序列从前往后扫,相连的相同字母算一个块,最后使得所有块最少。这个其实是个从前往后扫的问题,只要枚举最后一位是哪个,比如i-1块的最后一位是w,且w在第i块中确实有,则 f[i][j]=min(本身,f[i-1][w]+chunks[i]-1), chunks[i]表示该块有本身有多少个小块。#include #include #include #define INF 1<<30char ch[1010];int r
阅读全文
摘要:求一个序列中 的2*n-1个数字 ,前n+1个数字为严格升序 后n+1个为严格降序,求最长的长度一开始还没想清楚怎么解,其实就是一个LCS问题,从头到尾以及反序求一下LCS由于 d[i]为包含了自身的LCS,所以每次比较 min(d1[i],d2[i]),再 2*min-1即可,d1和d2分别为正序和反序的LCS。由于时间卡的紧,要用之前学过的压栈法求LCS,时间复杂度为n*logn,中间出了一些问题,首先就是保存每个节点的LCS值的时候,如果该点是大于sta[top],那自然LCS为top+1,但是如果不是的话,我一开始写成top,原来不是,是要二分的那个位置才是。。。。还有就是二分一开始调
阅读全文
摘要:一开始把它当成暴力来做了,即,从终点开始,枚举其最长的回文串,一旦是最长的,马上就ans++,再计算另外的部分。。。结果WA了事实证明就是一个简单DP,算出两个两个点组成的线段是否为回文,再用LCS的类似做法得到每个子结构的最优值。#include #include #define N 1010char s[N];int n,len,d[N][N],sum[N];int min(int a,int b){ if (a0) { tmp=1+sum[j-1]; } ...
阅读全文
摘要:这个题目上周的对抗赛的,美国2013区域赛的题目,上次比赛真惨,就做出一道题,最多的也只做出两道,当时想把这题做出来,一直TLE。这个题目用挂在Hunnu OJ的数据可以过,但UVALive上死活过不了,好像UVALive卡的时间不太对,没人过了这道题。我当初是想用一个dp[s]表示键入状态,然后由dp[0]开始逐渐向上深搜,结果就TLE了,后来比较了一下别人的代码,,果然我这样还是不行不管我怎么优化,我这一维数组,不能对某个状态马上就返回,因为随时可以再被更新,但是如果用个二维数组,dp[s][i],表示在状态为s的时候,键入第i个字符时候的最小键入数目,就可以只更新一次,下次再遇到这个情况
阅读全文
摘要:这个题目是个挺难表示的状态DP,因为不但要考虑上下还要考虑左右,在DP里面就没有什么下了咯,但也至少除了考虑左右还要考虑上所以先枚举出在同一行满足条件的状态 即 某状态 若 s&(s#include #include #include #define N 11using namespace std;int dp[105][1<<N-3][1<<N-3];int A[105],m,n,calc[1<<N],num,state[1<<N];void init(){ num=0; for (int i=0;i<(1<<m);i
阅读全文
摘要:这个题目搁置了这么久,终于搞完了。给n个人分配n个课程,已经告诉了你n个人对哪几门感兴趣,问最多有多少种分配方式我刚开始都没找到这怎么还可以状态dp,哪来的状态转移,想用暴力DFS,果断TLE的妥妥的。后来给殷犇发了这个题目,他还说你刷个这水题还刷得这包子劲,这题目就是后一行的状态由前一行得到,枚举当前这一行分配的状态,如果可行,就从后面的状态加过来由于状态只是从上一行转移过来,所以可以用滚动数组,用p表示当前,则!p就为上一行的,每次结束再把p置反即可。#include #include #include #define ll long longusing namespace std;int
阅读全文
摘要:这道题目的DP思想挺先进的,用状态DP来表示各个子巧克力块。原本是要 dp(S,x,y),S代表状态,x,y为边长,由于y可以用面积/x表示出来,就压缩到了只有两个变量,在转移过程也是很巧妙,枚举S的子集s0,然后 s1=S-s0来代表除该子集的另一个集合,接下来分两种情况,如果这个子集是通过把 S保留x,切割y,则转移到dp(s0,x)和dp(s1,x),另一种情况是转移到dp(s0,y)和dp(s1,y)。为了更加缩小状态,统一把转移方程的 x换成 min(x,sum[S]/x),sum为该状态下的面积#include #include #include //#include #defin
阅读全文
摘要:这个题目我最初的做法沿用树形DP的做法,设置一个 dp[i][0]表示机器人在i点不回去的最短路径,dp[i][1]表示机器人在i点回去的最短路径,规划方向为i-1向i转移,结果发现这个不能用树形的结构去描述,当前状态不能仅仅靠前一个状态就决定好了,对于后面的点来说,可能当前点走另外一条路会好一些故,最后还是使用了书上的结构,其实也很简单,用d[i],表示收完从1-i所有的垃圾并送回原点的垃圾桶的最优距离,显然,最终结果就是d[n];则,如果某个j点满足 w(j+1,i)#include #include #include using namespace std;int d[100010];i
阅读全文
摘要:刚看到这个题目不知道怎么个DP法,有点难想到解法如下设置dp[i][j]代表i到j这段子序列能获得的最大值,这样,枚举m=min(m,dp[i+1到j][j],dp[i][i到j-1]),m就代表了给另一个人的,就可求得就只能取到 dp[i][j]-sum(i,j)-m,这样,sum为该段序列总和,只需简单的数列前缀和即可求得sum,这样,只需枚举m值,不断向下进行记忆化搜索,即可求得终结果。#include #include #include using namespace std;int n;int dp[110][110];int vis[110][110];int s[110];int
阅读全文
摘要:就是经典约瑟夫环问题的裸题我一开始一直没理解这个递推是怎么来的,后来终于理解了假设问题是从n个人编号分别为0...n-1,取第k个,则第k个人编号为k-1的淘汰,剩下的编号为 0,1,2,3...k-2,k,k+1,k+2...此时因为从刚刚淘汰那个人的下一个开始数起,因此重新编号把k号设置为0,则k 0k+1 1...0 n-k1 n-k+1假设已经求得了n-1个人情况下的最终胜利者保存在f[n-1]中,则毫无疑问,该胜利者还原到原来的真正编号即为 (f[n-1]+k)%n (因为第二轮重新编号的时候,相当于把每个人的编号都减了k,因此重新+k即可恢复到原来编号)。由此,我们可以想象,当最.
阅读全文

浙公网安备 33010602011771号