2017暑假集训 div1 DP(2)

来源:互联网 发布:travelling light知乎 编辑:程序博客网 时间:2024/06/05 16:52
poj 3186

题意:给一串数字,每次可以从最左端和最右端拿去一个数字,得到的价值是本身数字乘以拿去的次序

做法:区间DP 每次枚举长度然后枚举起点,从左右两端开始转移即可DP[I][J]代表I是起点J 是终点的最大值。
#include <iostream>#include <algorithm>#include <string.h>#include <stdio.h>#include <queue>using namespace std;int n;int a[3000];int dp[3000][3000];int main(){    scanf("%d",&n);    for(int i=1;i<=n;++i) scanf("%d",&a[i]);    memset(dp,0,sizeof(dp));    for(int i=1;i<=n;++i) dp[i][i]=a[i]*n;    for(int len=1;len<=n-1;++len)    {        for(int s=1;s+len<=n;++s)        {            dp[s][s+len]=max(dp[s][s+len],dp[s+1][s+len]+a[s]*(n-len));            dp[s][s+len]=max(dp[s][s+len],dp[s][s+len-1]+a[s+len]*(n-len));        }    }    printf("%d\n",dp[1][n]);    return 0;}

HDU 1079
简单线性DP。


HDU 2589
题意:给你一个n*n的矩阵,矩阵中只含有26个小写字母,求其中最大的对称矩阵的大小
做法:DP[I][j]是从(i,j)往左上角开始的最大对称矩阵,那么要求dp[I][j]只需要枚举新加的两条边是否对应相等,然后分两种情况即可

#include <iostream>#include <algorithm>#include <stdio.h>#include <string.h>using namespace std;char str[1100][1100];int dp[1100][1100];int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        if(n==0) break;        for(int i=0;i<n;++i) scanf("%s",str[i]);        int ans=0;        for(int i=0;i<n;++i)        {            for(int j=0;j<n;++j)            {                if(i==0) dp[i][j]=1;                else                {                    int a=i , b=j;                    while(str[a][j]==str[i][b])                    {                        a--; b++;                        if(a<0||b>n) break;                    }                    a=i-a;                    if(a>dp[i-1][j+1]) dp[i][j]=dp[i-1][j+1]+1;                    else  dp[i][j]=a;                }                ans=max(dp[i][j],ans);            }        }        printf("%d\n",ans);    }    return 0;}





原创粉丝点击