HDU 1243反恐训练营(最长公共子序列简单应用)
问题描述:
这次训练比赛的规则是这样的:
1、每个队员从出发点开始,沿着一条唯一的笔直道路跑直到终点,途中不允许往回跑,否则将被取消比赛资格。
2、出发前,每个队员的枪膛内都被装了顺序一样的、用小写英文字母标明类型的子弹序列,每位队员被告知这一序列的信息;同时,每位队员也被告知恐怖分子即将出现的序列和类型(同样用小写英文字母标明类型)。
3、在跑动的过程中,若发现“恐怖分子”,特警队员可以选择用枪击毙他,来得到写在“恐怖分子”胸前的得分,但是前提是他使用的子弹类型必须和“恐怖分子”类型相同,否则,即使击毙了“恐怖分子”,也得不到分数;当然选择不击毙他也是可以的,这样他不会从那个“恐怖分子”身上得到分数。
4、允许特警队员放空枪,这样可以消耗掉型号不对的子弹而不至于杀死“恐怖分子”(当然每个特警队员都不会愚蠢到不装消音装置就放空枪,以至于吓跑“恐怖分子”),等待枪口出现正确型号的子弹击毙他得分。
这里,我们假定:
1、对于每个队员,途中出现恐怖分子的地点、时间、类型也是完全一样的。
2、每颗子弹都是质量合格的,都可以发挥杀伤效力
3、由于队员各个都是神枪手,一旦他选择了正确的子弹,向目标射击,目标100%被爆头
4、每个队员的记忆力超强,能记住所有子弹序列信息和恐怖分子序列信息。
5、每个队员体力足够好,能跑完全程,并做他想要做的
6、“恐怖分子”是不动的,小范围内不存在多于一个的恐怖分子;
炜炜需要你的帮助,告诉他如何做,才能得到最高的分数。现在如果告诉你出发时枪膛内子弹的序号和型号、恐怖分子出现的序号和类型,你能告诉炜炜他最多能得到多少分数吗?
样例输入:
输入数据的第一行有一个整数N表示子弹和恐怖分子的类型数。随后的一行是各种恐怖分子类型的一行字母,两个字母之间没有任何字符。接下来的一行是击毙上一行对应位置恐怖分子类型的得分数,每个分数之间恰有一个空格。第三第四行分别表示开始时枪膛内子弹的序列(左边的先打出)和恐怖分子出现的序列(左边的先出现),字母之间都没有任何字符。
每个测试数据之间没有空格和空行。你的程序必须通过全部测试数据,才能被判为AC。
3
abc
1 1 1
abc
ccc
3
abc
1 1 1
ccc
aba
样例输出:
对于每一个测试数据,输出炜炜最多能得到的分数。
1
0
该问题是求子弹序列和恐怖分子序列的最长公共子序列,由于不同子弹击中后所对应的分数不同,所以将每个公共字符所对应长度加1替换为加该字符所对应的分数即可。
AC代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int n;
while(~scanf("%d", &n) && n != 0)
{
char type[n + 1];
scanf("%s", &type);
int type_score[30];
for(int i = 0; i < n; i++)
{
int temp;
scanf("%d", &temp);
type_score[type[i] - 'a'] = temp;
}
string bullet, terrorist;
cin >> bullet >> terrorist;
int b_len = bullet.length();
int t_len = terrorist.length();
int c[b_len + 1][t_len + 1];
for(int i = 1; i <= b_len; i++)
{
c[i][0] = 0;
}
for(int i = 1; i <= t_len; i++)
{
c[0][i] = 0;
}
c[0][0] = 0;
for(int i = 1; i <= b_len; i++)
{
for(int j = 1; j <= t_len; j++)
{
if(bullet[i - 1] == terrorist[j - 1])
{
c[i][j] = c[i - 1][j - 1] + type_score[bullet[i - 1] - 'a'];
}
else
{
c[i][j] = max(c[i - 1][j], c[i][j - 1]);
}
}
}
printf("%d\n", c[b_len][t_len]);
}
return 0;
}