简单dp大合集

来源:互联网 发布:淘宝怎么改收货地址 编辑:程序博客网 时间:2024/04/30 00:00

poj 1088 - 滑雪(dfs记忆化搜索)

题意:

中文题略

思路:
dp[i][j]表示到达(i,j)点的最长路径长度

代码:
//#pragma comment(linker, "/STACK:102400000,102400000")#include "iostream"#include "cstring"#include "string"#include "cmath"#include "queue"#include "cstdio"#include "algorithm"#include "cctype"#include "vector"#include "map"#include "stack"using namespace std;typedef long long LL;const int INF = 0x6fffffff;const int inf = 522133279;const LL llinf = 1e30;const double eps = 1e-10;int g[110][110];int dir[4][2] = {0,1,1,0,0,-1,-1,0};int dp[110][110];int x,y;int maxc=-1;int border(int xx , int yy){    return (xx >= 0 && xx < x) && (yy >= 0 && yy < y);}int dfs(int m , int n){    if(dp[m][n])            //已经有了最大值记录,避免重复计算        return dp[m][n];    int maxn = 0;    for(int i = 0 ; i < 4 ; i++)    {        int tmpx = m+dir[i][0];        int tmpy = n+dir[i][1];        if(border(tmpx,tmpy) && g[m][n] > g[tmpx][tmpy])       //获得最大值            dp[m][n] = max(dp[m][n] , dfs(tmpx,tmpy)+1);    }    return dp[m][n];}int main(){    while(~scanf("%d%d" , &x,&y))    {        memset(dp,0,sizeof(dp));        for(int i = 0 ; i < x ; i++)            for(int j = 0; j < y ; j++)                scanf("%d",&g[i][j]);        for(int i = 0 ; i < x ; i++)            for(int j = 0; j < y ; j++)                maxc = max(maxc,dfs(i,j));        printf("%d\n",maxc+1);    }    return 0;}

hdu 4800 - Josephina and RPG


题意:
有Size = C(3,m)种组合兵种(0开始编号),给出一个Size*Size的矩阵g,g[i][j]表示i组合打赢j组合的概率,如果某一组i打赢了j,i可以换成j的组合继续攻打敌人
给出一组N个组合的序列,问打赢它们的最大概率是多少

思路:
dp[i][j] 表示打败第i个组合之后我方当前队伍为j
order[i]表示第i组敌人的编号

状态转移方程:
dp[i][j] = max(dp[i-1][j]*g[j][order[i]] , dp[i][j]);                              打败i-1的是j组合,仍旧用j去攻打i
dp[i][order[i]] = max(dp[i][order[i]] , dp[i-1][j] * g[j][order[i]]);         打败i-1的是j组合,接下来换成被j打败的order[i]兵种去攻打

代码:
//#pragma comment(linker, "/STACK:102400000,102400000")#include "iostream"#include "cstring"#include "string"#include "cmath"#include "queue"#include "cstdio"#include "algorithm"#include "cctype"#include "vector"#include "map"#include "stack"using namespace std;typedef long long LL;const int INF = 0x6fffffff;const int inf = 522133279;const LL llinf = 1e30;const double eps = 1e-10;int M,N;double g[200][200];double dp[10010][200];                //dp[i][j] 打败第i个组合之后我方当前队伍为jint order[10010];int main(){    while(~scanf("%d" , &M))    {        memset(dp,0,sizeof(dp));        int Size = (M-1)*(M-2)*M/6;        for(int i = 0 ; i < Size ; i++)            for(int j = 0 ; j < Size ; j++)                scanf("%lf" , &g[i][j]);        scanf("%d" , &N);        for(int i = 1 ; i <= N ; i++)            scanf("%d" , order+i);        for(int i = 0 ; i < Size ; i++)            dp[0][i] = 1;        for(int i = 1 ; i <= N ; i++)            for(int j = 0 ; j < Size ; j++)            {                dp[i][j] = max(dp[i-1][j]*g[j][order[i]] , dp[i][j]);                dp[i][order[i]] = max(dp[i][order[i]] , dp[i-1][j] * g[j][order[i]]);            }        double maxn = -1;        for(int i = 0 ; i < Size ; i++)            maxn = max(maxn,dp[N][i]);        printf("%.6lf\n" , maxn);    }    return 0;}


hdu 2084 - 数塔(记忆化)

题意:
中文题略

思路:
dfs构造dp方程

代码:
//#pragma comment(linker, "/STACK:102400000,102400000")#include "iostream"#include "cstring"#include "string"#include "cmath"#include "queue"#include "cstdio"#include "algorithm"#include "cctype"#include "vector"#include "map"#include "stack"using namespace std;typedef long long LL;const int INF = 0x6fffffff;const int inf = 522133279;const LL llinf = 1e30;const double eps = 1e-10;const int MOD=20121014;int dp[110][110];int g[110][110];int n;int dfs(int hang,int pos){    if(hang == n)        return g[hang][pos];    if(dp[hang][pos])        return dp[hang][pos];    return dp[hang][pos] = max(dfs(hang+1,pos), dfs(hang+1,pos+1))+g[hang][pos];}int main(){    int t;    scanf("%d",&t);    while(t--)    {        memset(dp,0,sizeof dp);        scanf("%d",  &n);        for(int i = 1 ; i <= n ; i++)            for(int j = 1 ; j <= i ; j++)                scanf("%d" , &g[i][j]);        printf("%d\n" , dfs(1,1));    }    return 0;}

hdu 2571 - 命运

题意:
中文题略

思路:
还是记忆化,dfs构造特别清晰

代码:
//#pragma comment(linker, "/STACK:102400000,102400000")#include "iostream"#include "cstring"#include "string"#include "cmath"#include "queue"#include "cstdio"#include "algorithm"#include "cctype"#include "vector"#include "map"#include "stack"using namespace std;typedef long long LL;const int INF = 0x6fffffff;const int inf = 522133279;const LL llinf = 1e30;const double eps = 1e-10;const int MOD=20121014;int m,n;int g[30][1100];int dp[30][1100];int dfs(int x , int y){    if(dp[x][y])        return dp[x][y];    if(x == m && y == n)        return g[m][n];    int maxc = -inf;    if(x < m)        maxc = max(maxc,dfs(x+1,y));    if(y < n)        maxc = max(maxc,dfs(x,y+1));    for(int i = 2 ; i*y <= n ; i++)        maxc = max(maxc,dfs(x,i*y));    return dp[x][y] = maxc + g[x][y];}int main(){    int t;    scanf("%d" , &t);    while(t--)    {        memset(dp,0,sizeof(dp));        scanf("%d%d" , &m,&n);        for(int i = 1 ; i <= m ; i++)            for(int j = 1 ; j <= n ; j++)                scanf("%d",&g[i][j]);        printf("%d\n",dfs(1,1));    }    return 0;}





原创粉丝点击