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;
}