题目有难度,有点类似于lcs的分析,题目大意为:每个case给定两个字符串,要求在两个串中插入必要的‘-‘使得两串匹配按照题目所给定value值最大。理解题意时要注意如下:
1)只能在原串中插入字符’-‘,使得两串的长度相等,但原串本身字符的顺序不能改变,这是该题的关键点
2)可以在任意位置插入任意数量的’-‘,只要不违反条件1)
理解了上述两点后,接着就要确定dp及状态方程了。分析如下:
我们令dp[i][j]表示第一个串中前i个字符,第二个串中前j个字符,所组成的两个字符串的最大value。则第二个字符串中最末尾的字符next[j]可以与第一个字符串中的字符first[k]匹配(1<=k<=i ),同时可以匹配符号‘-’,而匹配符号可以分为多种情况,符号‘-’的位置不同,则表达式就不同,但均可以归为一种情况即:dp[i][j-1]+value[1][next[j]-'A']。
那么动态转移方程就出来了:dp[i][j]=max{dp[k-1][j-1]+value[first[k]-'A'][next[j]-'A']+value[1][first[index]-'A']}
详细见代码: 204K+32MS
#include <stdio.h>
#include <stdlib.h>
#define Max 110
#define Maxx(a,b) (a)>(b)?(a):(b)
char first[Max]; // 第一个串
char next[Max]; // 第二个串
char help[Max]; // 辅助数组
int dp[Max][Max];
int value[20][20]; //记录题意value
int Case;
int len1,len2; // 串长1和2
int main(){
int i,j,k,index; //初始化题意value
value[0][0]=5,value[0][1]=-3,value[0][2]=-1,value[0][6]=-2,value[0][19]=-1;
value[2][0]=-1,value[2][1]=-4,value[2][2]=5,value[2][6]=-3,value[2][19]=-2;
value[6][0]=-2,value[6][1]=-2,value[6][2]=-3,value[6][6]=5,value[6][19]=-2;
value[19][0]=-1,value[19][1]=-1,value[19][2]=-2,value[19][6]=-2,value[19][19]=5;
value[1][0]=-3,value[1][2]=-4,value[1][6]=-2,value[1][19]=-1;
scanf("%d",&Case);
while(Case--){
scanf("%d",&len1);
getchar();
scanf("%s",help); //转化为第一个串,以1开头
for(i=1;i<=len1;i++)
first[i]=help[i-1];
scanf("%d",&len2);
getchar();
scanf("%s",help);
for(i=1;i<=len2;i++) // 同理
next[i]=help[i-1];
dp[0][0]=0; //初始化两个长度均为0的串匹配最大value为0
//初始化第二个串长度为0,第一个串长度为i(1<=i<=len1)匹配的最大长度即为第一个串中的每个字符与符号’-‘匹配
for(i=1;i<=len1;i++){
dp[i][0]=0;
for(j=1;j<=i;j++)
dp[i][0]+=value[1][first[j]-'A'];
}
//同理,初始化第一个串长度为0
for(i=1;i<=len2;i++){
dp[0][i]=0;
for(j=1;j<=i;j++)
dp[0][i]+=value[1][next[j]-'A'];
}
for(i=1;i<=len1;i++) //求解dp,注意顺序必须为这样,才能利用已知dp求解未知dp
for(j=1;j<=len2;j++){
//两种特殊情况,特殊处理,分别为末尾匹配和与’-‘匹配
dp[i][j]=dp[i-1][j-1]+value[first[i]-'A'][next[j]-'A'];
dp[i][j]=Maxx(dp[i][j],dp[i][j-1]+value[1][next[j]-'A']);
for(k=1;k<i;k++){ // 一般情况,当1<=k<i时
int temp=dp[k-1][j-1]+value[first[k]-'A'][next[j]-'A'];
for(index=k+1;index<=i;index++)
temp+=value[1][first[index]-'A'];
dp[i][j]=Maxx(dp[i][j],temp);
}
}
printf("%d\n",dp[len1][len2]); //输出最大value
}
return 0;
}