动态规划的题,根据题意是从前往后推好还是从后往前遍历,要看自己的判断
哎呀呀,我真的是太菜太菜了,慢慢来吧,,,希望以后。。。
一般递推都是从后往前,
代码一:用了结构体,,
#include<iostream>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<map>
using namespace std;
const int M=210;
struct Segement
{
int color;
int len;
};
Segement segements[M];
int score[M][M][M];
int Click_Box(int i,int j,int len)
{
int result,r,k;
if(score[i][j][len]!=-1)
return score[i][j][len];
result=(segements[j].len+len)*(segements[j].len+len);
if(i==j)
return result;
result+=Click_Box(i,j-1,0);
for(k=i; k<=j-1; ++k)
{
if(segements[k].color!=segements[j].color)
continue;
r=Click_Box(i,k,segements[j].len+len)+Click_Box(k+1,j-1,0);
result=max(result,r);
}
score[i][j][len]=result;
return result;
}
int main()
{
int t,T,last,num,i,n,m;
scanf("%d",&T);
for(t=1; t<=T; ++t)
{
last=0;
num=-1;
memset(score,-1,sizeof(score));
scanf("%d",&m);
for(i=0; i<m; ++i)
{
scanf("%d",&n);
if(n!=last)
{
num++;
segements[num].len=1;
segements[num].color=n;
last=n;
}
else
segements[num].len ++;
}
// for(i=0;i<num;++i)
// cout<<segements[i].len<<" "<<segements[i].color<<endl;
printf("Case %d: %d\n",t,Click_Box(0,num,0));
}
return 0;
}
代码2:自己写的
#include<iostream>
#include<algorithm>
#include<fstream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<cctype>
#include<vector>
#include<limits.h>
#include<queue>
using namespace std;
int dp[210][210][210];
int color[210];
int leng[210];
int Dp(int i,int j,int len)
{
if(dp[i][j][len]!=-1)
return dp[i][j][len];
int ans=(leng[j]+len)*(leng[j]+len);
if(i==j)
return ans;
ans+=Dp(i,j-1,0);
for(int k=i; k<j; k++)
{
if(color[k]==color[j])
ans=max(ans,Dp(i,k,leng[j]+len)+Dp(k+1,j-1,0));
}
dp[i][j][len]=ans;
return ans;
}
int main()
{
int t,ans,n,m,num,j,l,i;
scanf("%d",&t);
for(l=1; l<=t; ++l)
{
scanf("%d",&n);
memset(dp,-1,sizeof(dp));
for(ans=-1,i=1,j=0; i<=n; ++i)
{
scanf("%d",&m);
if(ans!=m)
{
j++;
color[j]=m;
leng[j]=1;
ans=m;
}
else
{
leng[j]++;
}
}
num=Dp(0,j,0);
printf("Case %d: %d\n",l,num);
}
return 0;
}
3.采用递推解法,
#include<iostream>
#include<algorithm>
#include<fstream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<cctype>
#include<vector>
#include<limits.h>
#include<queue>
using namespace std;
int dp[205][205][205];
int color[205]; //记录颜色
int len[205]; //对应的长度
int pre[205]; //记录与该颜色相同的前一个
int pos[205];
int main()
{
int n,pr,i,j,k,l,t,tot,a,length,Case=0;
scanf("%d",&t);
while(t--)
{
n=0;
pr=-1;
scanf("%d",&tot); //总共有几个小块
for(i=1; i<=tot; ++i)
{
scanf("%d",&a);
if(a!=pr)
{
color[++n]=a;
pr=a;
len[n]=1;
}
else
++len[n];
}
memset(dp,0,sizeof(dp));
memset(pos,0,sizeof(pos));
for(i=1; i<=n; ++i)
{
pre[i]=pos[color[i]]; //记录与此颜色相同的前坐标
pos[color[i]]=i;
}
for(length=0; length<n; ++length) //for循环内的顺序不可以改变,他是从头到尾求每个点依次加length++,先求每个短区间,,逐渐求大区间
{
for(i=1;; ++i)
{
j=i+length;
if(j>n)
break;
for(k=0; k<=tot; ++k)
{
dp[i][j][k]=dp[i][j-1][0]+(len[j]+k)*(len[j]+k);
for(l=pre[j]; l>=i; l=pre[l]) //这个pre数组运用的很巧妙
dp[i][j][k]=max(dp[i][j][k],dp[i][l][k+len[j]]+dp[l+1][j-1][0]);
}
}
}
printf("Case %d: %d\n",++Case,dp[1][n][0]);
}
return 0;
}