区间动规主要有两种方法:
一、是先想出递归式,然后将之转化为滚动数组。
二、或者从小区间贪到大区间。
POJ 1159 点击打开链接
AC代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
char a[5005];
short dp[5005][5005];
int min(int a,int b)
{
return a<b?a:b;
}
int main()
{
int n;
int ans;
int i,j;
while(cin>>n)
{
memset(dp,0,sizeof dp);
cin>>a+1;
//cout<<a+1;
for(i=1;i<=n;i++)
{
dp[i][i]=0;
}
int len;
for(len=2;len<=n;len++)
{
for(i=1;i<=n-len+1;i++)
{
j=i+len-1;
if(a[i]==a[j])
dp[i][j]=dp[i+1][j-1];
else
{
dp[i][j]=min(dp[i][j-1],dp[i+1][j])+1;
}
}
}
cout<<dp[1][n]<<endl;
}
return 0;
}
POJ 2955 点击打开链接
AC代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[105][105];
char str[1005];
int main()
{
int i,j,o,t;
while(cin>>str,str[0]!='e')
{
int l=strlen (str);
for(i=0;i<l;i++)
for(j=0;j<l;j++)
dp[i][j]=0;
for(o=2;o<=l;o++)
{
for(i=0;i<l-o+1;i++)
{
j=i+o-1;
for(t=i;t<j;t++)
{
dp[i][j]=max(dp[i][j],dp[i][t]+dp[t+1][j]);
if((str[i]=='('&&str[j]==')')||(str[i]=='['&&str[j]==']'))
dp[i][j]=max(dp[i][j],dp[i+1][j-1]+2);
}
}
}
cout<<dp[0][l-1]<<endl;
}
return 0;
}
POJ 1141 点击打开链接
AC代码如下:
#include<iostream>
#include<cstring>
using namespace std;
int dp[205][205];
int dd[205][205];
char str[1005];
int l,minn;
int i,j,t,x;
void PRINTF(int s,int e)
{
if(s>e)
return ;
else
{
if(s==e)
{
if(str[s]=='('||str[s]==')')
cout<<"()";
else cout<<"[]";
}
else{
if(dd[s][e]>=0)
{
PRINTF(s,dd[s][e]);
PRINTF(dd[s][e]+1,e);
}
else
{
cout<<str[s];
PRINTF(s+1,e-1);
cout<<str[e];
}
}
}
}
void DP()
{
for(i=0;i<l;i++)
dp[i][i]=1;
memset(dd,0,sizeof dd);
dd[0][0]=-1;
for(x=2;x<=l;x++)
{
for(i=0;i<l-x+1;i++)
{
j=i+x-1;
dd[i][j]=i;
minn=dp[i][i]+dp[i+1][j];
for(t=i+1;t<j;t++)
{
if(dp[i][t]+dp[t+1][j]<minn)
{
minn=dp[i][t]+dp[t+1][j];
dd[i][j]=t;
}
}
dp[i][j]=minn;
if((str[i]=='('&&str[j]==')')||(str[i]=='['&&str[j]==']'))
if(minn>dp[i+1][j-1])
{
dp[i][j]=dp[i+1][j-1];
dd[i][j]=-1;
}
}
}
//cout<<dp[0][l-1]<<endl;
}
int main()
{
cin>>str;
l=strlen (str);
DP();
PRINTF(0,l-1);
cout<<endl;
return 0;
}