随笔分类 - DP
摘要:令res[i][j]表示从str[i]到str[j]需要添加字符的个数;如果str[k]与str[i]匹配, res[i][j]=min(res[i][j], res[i+1][k-1]+res[k+1][j]);如果str[k]与str[j]匹配, res[i][j]=min(res[i][j],res[i][k-1]+res[k+1][j-1] );如果str[k]与str[i]和str[j]都不匹配,res[i][j]=min(res[i][j],res[i][k-1]+res[k+1][j]+1 );#include<iostream>#include<cstdio&
阅读全文
摘要:令res[i][s1][k]表示第i行状态为s1,前i行摆放棋子的个数为k的方案个数;res[i][s1][k]=∑res[i-1][s2][k-inum]; inum表示第i行摆放的棋子个数,s1,s2表示第i行和第i-1行的状态,两种状态能够相容。#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define lld long long lld res[11][1025][101];int n,m;int init(int j,int state,int inu
阅读全文
摘要:经典的状态压缩和我的上一篇几乎一样,总的来说共有三种摆放方式:1、竖放 2、横放 3、不放代码如下:#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define lld __int64 lld res[13][5000];int n,m;int dfs(int i,int j,int s1,int s2,int b1,int b2){ if(j>=m) { if(b1==0 && b2==0) res[i][s1]+=res[i-1][s2]
阅读全文
摘要:看了大牛的博客才知道这道题是周伟《状态压缩》中的原题,搜了一下该文档,并仔细看了一下,让我茅塞顿开,原来是这样的:令res[i][j]表示前i-1行全部铺满,第i行状态为j的方法总数(某位置有木板则为1,反之则为0);当我们确定了第i行的状态,才能够确定第i-1行的状态。所以我们枚举第i行的所有状态就ok了。总的来说一共有7放法:1、 长方形木板竖放2、 长方形木板横放3、 缺左上角的L形木板4、 缺右上角的L形木板5、 缺左下角的L形木板6、 缺右下角的L形木板7、 不放假如我们用dfs来遍历的话,我们可以用 i,j, s1,s2,b1, b2;分别表示当前第i行、当前第j列、i-1行状态为
阅读全文
摘要:状态转移方程如下:res[i][j]=max{res[i-1][j-1]+f(str1[i],str2[j]),res[i-1][j]+f(str1[i],’-‘),res[i][j-1]+f(‘-‘,str2[j])};#include<iostream>#include<cstdio>#include<cstring>using namespace std;char str1[101],str2[101];int d[5][5]={ {5,-1,-2,-1,-3}, {-1,5,-3,-2,-4}, {-2,-3,5,-2,-2}, {-1,-2,-2,
阅读全文
摘要:又一道双进程DP,状态转移方程如下:f(k,i,j)=max(f(k-1,i,j),f(k-1,i-1,j),f(k-1,i,j-1),f(k-1,i-1,j-1))然后f(k,i,j)加上(i,k-i)和(j,k-j)上的interesting locations。注意i和j相等的情况。#include<iostream>#include<cstdio>#include<cstring>using namespace std;int map[110][110];int res[211][110][110];inline int max(int a,int
阅读全文
摘要:双调欧几里得旅行商问题:http://blog.sina.com.cn/s/blog_51cea4040100gkcq.htmlf(i,j)表示第一个人走到i点,第二个人走到j点所行走的最短距离,前i个都已经走过。所以将要到达第i个点时,第i个点有可能交给第一个人,也有可能交给第二个人,两种情况下与f(i-1,j) 都有什么关系呢?第一种情况下:f(i,j)=min{f(i,j),f(i-1,j)+dist(i-1,i)};第二种情况下:f(i,i-1)=min{f(i,i-1),f(i-1,j)+dist(j,i)};(f(i,i-1)==f(i-1,i))代码如下:#include<
阅读全文
摘要:Nyoj 61 传纸条前几天无意中看到多进程DP,原来我苦恼很长时间的传纸条问题竟然是双进程DP,搜了几篇大牛的关于双进程DP的文章,有些思路了:拿传纸条问题来说吧,其实就是找两条从左上角到右下角不相交的路径(除了头和尾),使路径上的和最大。因为路径不能相交,所以我们必须同时考虑两个人的位置,若两人的位置设为x1,y1, x2,y2,状态转移方程可以写成如下形式:f(x1,y1,x2,y2)=max{f(x1-1,y1,x2-1,y2),f(x1-1,y1,x2,y2-1),f(x1,y1-1,x2-1,y2),f(x1,y1-1,x2,y2-1)}+map[x1][y1]+map[x2][y
阅读全文
摘要:典型的背包问题,状态转移方程如下:res[i][j] 表示用i的忍耐度杀j个怪兽获得的最大经验值。res[i][j]=max(res[i-weight[k]][j-1]+value[k], res[i][j]);代码如下:#include<iostream>#include<cstdio>#include<cstring>using namespace std;int weight[101],value[101],res[101][101];int max(int a,int b){ return a > b ? a : b;}int work(int
阅读全文
摘要:题意:给出两串,两串顺序不变看能否组成第三个串。此题深搜和DP都能解决:深搜的话需要几个强有力剪枝条件1、 第三个串最后一个字符要么是串1的最后一个字符,要么是串2的最后一个字符2、 按照串1的顺序对串3进行搜索,若不匹配则该字符必是串2的下一个字符。#include<iostream>#include<cstdio>#include<cstring>using namespace std;char first[202],second[202],third[402],Left[401];int sign[402];bool flag;int check(){
阅读全文
摘要:一道简单的树形DP,可以这么想:每个节点有可能选择也有可能不选择,而且各个子树相互独立,我用DP[i][0]表示节点i不选择所需要的最少士兵,DP[i][1]表示i节点选择所需要的最少士兵。假如j是i的儿子,因此状态转移方程可以写成如下形式:DP[i][0]+=DP[j][1] ;DP[i][1]+=min(DP[j][0],DP[j][1]);#include<iostream>#include<cstdio>#include<cstring>using namespace std;struct node{ int i,next;}S[15001];int
阅读全文
浙公网安备 33010602011771号