您的位置:首页 > 其它

pat1045Favorite Color Stripe (30)

2015-10-13 21:07 141 查看
题意分析:

(1)给出一个有若干个数的偏好序列,同时给出另一个任意的数组,并且参照前面序列中元素出现的相对顺序(某些元素可以丢弃)依次从前往后选择数组中的元素组成一个新的数组,求这个数组的最大长度。

(2)由于求解的是从数组A中下标范围到i这个序列的顺序,选择数组B中下标范围到j的最长数组的长度,可以分解为:A中下标范围到i,B中下标范围到j-1与A中下标范围到i-1,B中下标范围到j这两个子问题,若求得这两个子问题的最大值,再根据A中第i个位置和B中第j个位置的值,合并之后得到原始问题的解,然后按照这个思路递归求解。使用二维数组maxLength[i][j],表示从数组A中前i个元素在数组B中前j个元素能够找到的最大序列长度。

可能坑点:

(1)使用动态规划的题一般会有点难度,按照分析(2),此题的A、B数组的下标从1开始,这样才能使递归的最后一层(动态规划中递归的最后一层)不至于数组越界。

解法一:直接使用递归加引用

#include <iostream>

using namespace std;
int like[201]={0};
int given[10001]={0};
int length[201][10001]={0};

int DP(int start,int end)
{
int &ans=length[start][end];
if(ans>0)return ans;
if(start==0||end==0)return ans=0;
int i=DP(start-1,end);
int j=DP(start,end-1);
int flag=(like[start]==given[end]?1:0);
return ans=(i>j?i:j)+flag;
}
int main()
{
int N,M,L;
cin>>N>>M;
int i;
for(i=0;i<M;i++)cin>>like[i+1];
cin>>L;
for(i=0;i<L;i++)cin>>given[i+1];
cout<<DP(M,L)<<endl;
return 0;
}


解法二:借助记忆化数组

#include <iostream>

using namespace std;
int like[201]={0};
int given[10001]={0};
int length[201][10001]={0};
int getMaxLength(int row,int col)
{
int i,j,max;
for(i=1;i<=row;i++)
{
for(j=1;j<=col;j++)
{
max=length[i-1][j-1];
if(length[i-1][j]>max)max=length[i-1][j];
if(length[i][j-1]>max)max=length[i][j-1];
if(like[i]==given[j])length[i][j]=max+1;
else length[i][j]=max;
}
}
return length[row][col];
}
int main()
{
int N,M,L;
cin>>N>>M;
int i;
for(i=0;i<M;i++)cin>>like[i+1];
cin>>L;
for(i=0;i<L;i++)cin>>given[i+1];
cout<<getMaxLength(M,L)<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: