随笔分类 -  DP

摘要:简单树形DP,父节点要么去要么不去;res[i]=max(∑res[child[i]],∑res[child(child[i])]);#include<iostream>#include<cstdio>#include<cstring>using namespace std;struct node{ int i,next;}vert[201];char name[201][20];int head[201],res[201],go[201],nogo[201],N,count;int find(char * str){ int i; for(i=1;i< 阅读全文
posted @ 2012-06-09 10:32 书山有路,学海无涯 阅读(320) 评论(0) 推荐(0) 编辑
摘要:真是一个好题啊,还是想了好几天而且还WA了两次…….令res[i][j]表示前i个COW,Si为j时Fi的最大值。res[i][j]=max(res[i-1][j-Fi[i]],res[i][j]); 因为res[i][]只与res[i-1][]有关空间复杂度省去一维,就像01背包那样。因为j可能为负值,因此我们可以将j设置一个偏移量MOVE。#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define MAX 1234567890#define MOVE 100 阅读全文
posted @ 2012-06-08 09:55 书山有路,学海无涯 阅读(255) 评论(0) 推荐(0) 编辑
摘要:令res[i][j]表示前i个邮局负责前j个村庄的最小值。res[i][j]=res[i-1][k] + dist(k+1,j), (i<=j<=m,i-1<=k<j);#include<iostream>#include<cstdio>#include<cstring>using namespace std;int pos[301],res[35][301];#define MAX 1234567890int min(int a,int b){ return a < b ? a : b;}int dist(int i,int 阅读全文
posted @ 2012-05-31 20:40 书山有路,学海无涯 阅读(370) 评论(0) 推荐(0) 编辑
摘要:简单DP;状态转移方程如下:令len[i][j]表示串1前i个字符与串2前j个字符所得到的符合要求的串的最短长度。令res[i][j]表示串1前i个字符与串2前j个字符所得到的符合要求的最短串的方案数。len[i][j] = str1[i]==str2[j] ? len[i-1][j-1] +1: min(len[i-1][j],len[i][j-1])+1。若str1[i]==str2[j],res[i][j]=res[i-1][j-1];若 str1[i]!=str2[j] ,分三种情况:(1)len[i-1][j] < len[i][j-1] , res[i][j]=res[i-1 阅读全文
posted @ 2012-05-27 18:02 书山有路,学海无涯 阅读(293) 评论(0) 推荐(0) 编辑
摘要:简单DP#include<iostream>#include<cstdio>#include<cstring>using namespace std;char map[2][1410];int S[4][2][1410],s[4][2][1410],smax,Smax;int max(int a,int b){ return a > b ? a : b;}int work(int n,int e){ int i; for(i=1;i<=n;i++) { if(map[e][i]=='S') { if(map[1-e][i... 阅读全文
posted @ 2012-05-24 13:49 书山有路,学海无涯 阅读(179) 评论(0) 推荐(0) 编辑
摘要:简单的01背包,关键是找路径,通过此题对01背包找路径有了更深的认识了。#include<iostream>#include<cstdio>#include<cstring>#include<stack>using namespace std;int res[100010],nPath[100010],father[100010],data[110];int work(int goal,int n){ int i,j; memset(res,0,sizeof(res)); memset(nPath,0,sizeof(nPath)); memset 阅读全文
posted @ 2012-05-23 10:22 书山有路,学海无涯 阅读(153) 评论(0) 推荐(0) 编辑
摘要:纠结了一天也没有想到怎么用DP来做,看了看大牛的想法顿时茅塞顿开:结果是要求从i到j需要多少天,假如用res[i][j]来表示,那么假如我们知道res[1][i]和res[1][j]的话,res[i][j]=res[1][j]-res[1][i] (i<=j),因此转化为求res[1][i]和res[1][j];而2的整数次幂可以直接求出若用r[i]表示res[1][2^i]的结果r[i]=2*r[i-1]+i-1;画一画就可以看得出来。然后根据r[i]的值递归求任何一个res[1][k],如何递归呢?拿个Res[1][11]来说吧:先找出大于11的最大2的整数次幂8;Res[1][11 阅读全文
posted @ 2012-05-21 17:44 书山有路,学海无涯 阅读(211) 评论(0) 推荐(0) 编辑
摘要:题意:找出n的最小倍数,要求这个倍数十进制由1和2组成。看了discuss才知道确实可以用DP来做:令res[i][j]表示前i位对n取余为j是否可以得到。res[i][(10%n*j+1)%n]=res[i-1][j];res[i][(10%n*j+2)%n]=res[i-1][j];用到(a * b) % n=(a % n * b % n) % n;假如我们知道res[i][j]按照上面的公式顺着推很容易得到res[i+1][(10%n*j+1)%n]和res[i+1][(10%n*j+2)%n]的值,但是逆着推就不容易了。不管怎么说还是和01背包一个性质的。但是,提交后MLE,由于找路径 阅读全文
posted @ 2012-05-19 21:30 书山有路,学海无涯 阅读(320) 评论(0) 推荐(0) 编辑
摘要:简单DP,状态转移方程如下:res[i][j]=min(res[i][j],res[k][j-1]+fact(k+1,i)) (1<=j<i && j<=m, 1<=i<=n, 1<=k<i);fact(i,j)表示从i到j的系数。#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define MAX 1234567890int res[501][501],fact[501][501],horse[501]; 阅读全文
posted @ 2012-05-06 11:54 书山有路,学海无涯 阅读(194) 评论(0) 推荐(0) 编辑
摘要:令res[i][0]表示升级到i并且是正版的最小消费,res[i][1]表示升级到i并且是盗版的最小消费。res[i][0]=min(res[i][0],res[k][0]+edge(k,i)) (其中k必须可以升级到i,并且保证升级到i是正版);res[i][1]=min(res[i][1],res[k][x]+edge(k,i)) (其中res[k][x]表示正版盗版都行,关键保证升级到i是盗版)简单DP不用再说了,不过就是用到临界表来存储边,减小空间复杂度(姑且这样说)。#include<iostream>#include<cstdio>#include<c 阅读全文
posted @ 2012-05-03 21:13 书山有路,学海无涯 阅读(290) 评论(0) 推荐(0) 编辑
摘要:令res[i][j][0]表示数字和为i,数字平方和为j的可能性,要么为0要么为1,;res[i][j][1]表示至少有多少位数字。res[i][j][0]=res[i-k][j-k*k] ? 1 : 0;(1<=k<=9 , 1<=i<=900,1<=j<=8100)res[i][j][1]=min(res[i][j],res[i-k][j-k*k]+1);然后根据res[i][j][1]寻找最优解需要预处理一下,不然可能TLE,之前没有预处理TLE了n次。。。。。。。#include<iostream>#include<cstdio&g 阅读全文
posted @ 2012-05-03 12:57 书山有路,学海无涯 阅读(214) 评论(0) 推荐(0) 编辑
摘要:令res[i][j]表示从i到j是否是回文串。res[i][j]= (str[i]==str[j] && res[i+1][j-1]) ;接下来是如何找最少个数回文串,令inum[i]表示从1到i至少有多少个回文串,再次用DP;inum[i]=min(inum[j]+1),(其中res[j][i]==1,1<=j<i);最后根据inum[i]的值寻找一种可行的方案。O(n^2)的时间复杂度,O(n^2)的空间复杂度,网上还有更好的代码,竟然没有看懂#include<iostream>#include<cstdio>#include<cs 阅读全文
posted @ 2012-05-01 16:16 书山有路,学海无涯 阅读(221) 评论(0) 推荐(0) 编辑
摘要:搞了一天终于AC了,感觉题目有点问题,没有说有多个可行顺序的情况如何输出,然而测试数据是按照某一个顺序输出的。比如说:101 010 是按照111222输出,其实(如果题意我没有读错的话)121212 221112应该也是正确的。听说这道题有一定的改动,是不是出题人忽视了呢????令res[i][j]表示串1的前i个字符与串2的前j个字符是否能够按照规则分成两堆。res[i][j]= (res[i-1][j-1] && str1[i]!=str2[j]) || (res[i-2][j] && str1[i]!=str1[i-1]) || (res[i][j-2] 阅读全文
posted @ 2012-04-26 17:32 书山有路,学海无涯 阅读(255) 评论(0) 推荐(0) 编辑
摘要:简单背包,不过直接背包会超时,需要将每一种物品个数转化一下,方法是:将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为 1,2,4,...,2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+1>0的最大整数。例如,如果n[i]为13,就将这种 物品分成系数分别为1,2,4,6的四件物品。代码如下:#include<iostream>#include<cstdio>#include<cstring>using namespace std;int coin[7],res 阅读全文
posted @ 2012-04-20 11:06 书山有路,学海无涯 阅读(466) 评论(0) 推荐(0) 编辑
摘要:简单的树形DP,状态转移方程如下:令res[i]表示以i为根的子树获得的最大值;第i个人去或者不去。去的话,res[i]=value[i]+∑res[j], j表示i的孩子的孩子;不去的话,res[i]=∑res[k],k表示i的孩子;因此,res[i]=max{value[i]+∑res[j],∑res[k]};代码如下:#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define MAX 123456789struct node{ int i,next;}ve 阅读全文
posted @ 2012-04-08 10:38 书山有路,学海无涯 阅读(180) 评论(0) 推荐(0) 编辑
摘要:令res[i]表示到达第i个站点所用的最小费用;状态转移方程如下:res[i]=min{res[k]+f(L1,L2,L3)};(1<=k<i)代码如下:#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define MAX 1234567890int res[10001],dist[10001],L1,L2,L3,C1,C2,C3;int min(int a,int b){ return a < b ? a : b;}int work(int s 阅读全文
posted @ 2012-04-07 16:27 书山有路,学海无涯 阅读(178) 评论(0) 推荐(0) 编辑
摘要:简单的一道DP,只不过是每个状态与三个子状态有关,令res[i][j]表示从第一层到达map[i][j]的最小费用。本应该res[i][j]=min(res[i-1][j],res,[i][j+1],res[i][j-1])+map[i][j];但是在res[i][j+1]是在res[i][j]求出来之后才求出来,那我们怎么办呢?我们可以这样处理:每一行正反各求一次取最小值。#include<iostream>#include<cstdio>#include<cstring>#include<stack>using namespace std;# 阅读全文
posted @ 2012-04-06 19:14 书山有路,学海无涯 阅读(211) 评论(0) 推荐(0) 编辑
摘要:树形DP,令res[i][j]表示以i为根的子树删除j条边所保留的最大苹果数;res[i][j]=max(res[i][j],res[lChild][k]+res[rChild][j-k]+value[i]);(0<=j<=inum[i],0<=k<=inum[lChild])inum[i]表示以i为根的子树树枝的个数,value[i]以i为端点的树枝的苹果树。代码如下:#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define MAX 阅读全文
posted @ 2012-04-06 14:32 书山有路,学海无涯 阅读(183) 评论(0) 推荐(0) 编辑
摘要:一开始自己写了一个状态转移方程用res[i][j][k]表示前i个人已经完成A的j个部分B的k个部分所有过的最少时间。res[i][j][k]=min(res[i][j][k],max(res[i-1][j-s][k-t],s*A[i]+t*B[i]));很显然时间复杂度为O(n^5),显然是不可取的。看了大牛的思想后才知道可以用二分时间+DP来优化:令res[i][j]表示前i个人完成A的j个部分最多能完成B多少。res[i][j]=max(res[i][j],res[i-1][j-k]+(mid-k*A[i])/B[i]);当res[i][j]>=m 说明前i个人可以将任务完成,因此 阅读全文
posted @ 2012-04-04 16:40 书山有路,学海无涯 阅读(365) 评论(0) 推荐(0) 编辑
摘要:状态压缩经典题目令res[i][j][k]表示第i行状态为第j个状态时,第i-1行的状态为第k个状态时最多能摆放的个数,令state[i][j]表示第i行的第j个状态,kk[i][j]表示第i行第j个状态所放的个数,len[i]表示第i行的可能的状态数。则:res[i][j][k]=max(res[i][j][k],res[i-1][k][l]+kk[i][j]);(0<=l<len[i-2])结果就是:在res[n][j][k]中找一个最大的。状态压缩经典题目令res[i][j][k]表示第i行状态为第j个状态时,第i-1行的状态为第k个状态时最多能摆放的个数,令state[i] 阅读全文
posted @ 2012-04-01 22:08 书山有路,学海无涯 阅读(271) 评论(0) 推荐(0) 编辑

点击右上角即可分享
微信分享提示