ZOJ1027 Human Gene Functions
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=27
思路:算是最长公共子序列的拓展。。
设第一个字符串用char[] x存储
第二个字符串用char[] y存储
如果检索到 x 的第 i 个字符, y 的第 j 个字符,那么就只有三个选择方式。
1)x[i] 与 ‘-’配对
2)y[j] 与 ‘-’配对
3)x[i] 与 y[j] 配对
然后状态转移方程很容易推出来了。。
ps:提醒dp用边界预处理可以节省一定的时间
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class HumanGeneFunctions {
static Map<Character, Integer> m = new HashMap();
static Scanner sc = new Scanner(System.in);
static int[][] gene = new int[5][5];
static int[][] memo = new int[105][105];
static int[][] dp = new int[150][150];
static int memoSearch(char[] x, char[] y, int xLast, int yLast) {
if(memo[xLast+1][yLast+1] != -5) return memo[xLast+1][yLast+1];
if(xLast == -1 && yLast == -1) {
memo[xLast+1][yLast+1] = 0;
}
else if(xLast == -1)
memo[xLast+1][yLast+1] = memoSearch(x, y, xLast, yLast-1)+gene[4][m.get(y[yLast])];
else if(yLast == -1)
memo[xLast+1][yLast+1] = memoSearch(x, y, xLast-1, yLast)+gene[m.get(x[xLast])][4];
else
memo[xLast+1][yLast+1] = Math.max(Math.max(memoSearch(x, y, xLast-1, yLast-1)+gene[m.get(x[xLast])][m.get(y[yLast])]
, memoSearch(x, y, xLast-1, yLast)+gene[m.get(x[xLast])][4]),
memoSearch(x, y, xLast, yLast-1)+gene[4][m.get(y[yLast])]);
return memo[xLast+1][yLast+1];
}
static int recursion(char[] x, char[] y, int xLast, int yLast) {
if(xLast == -1 && yLast == -1) {
return 0;
}
if(xLast == -1)
return recursion(x, y, xLast, yLast-1)+gene[4][m.get(y[yLast])];
if(yLast == -1)
return recursion(x, y, xLast-1, yLast)+gene[m.get(x[xLast])][4];
return Math.max(Math.max(recursion(x, y, xLast-1, yLast-1)+gene[m.get(x[xLast])][m.get(y[yLast])]
, recursion(x, y, xLast-1, yLast)+gene[m.get(x[xLast])][4]),
recursion(x, y, xLast, yLast-1)+gene[4][m.get(y[yLast])]);
}
static void dp(char[] x, char[] y, int len1, int len2) {
for(int i = 1; i < len1; i++) {
dp[i][0] = dp[i-1][0] + gene[m.get(x[i-1])][4];
}
for(int i = 1; i < len2; i++) {
dp[0][i] = dp[0][i-1] + gene[4][m.get(y[i-1])];
}
for(int i = 1; i <= len1; i++) {
for(int j = 1; j <= len2; j++) {
dp[i][j] = Math.max(Math.max(dp[i-1][j-1] + gene[m.get(x[i-1])][m.get(y[j-1])]
, dp[i-1][j] + gene[m.get(x[i-1])][4])
, dp[i][j-1] + gene[4][m.get(y[j-1])]);
}
}
System.out.println(dp[len1][len2]);
}
static void preprocess() { //预处理基因数组
m.put('A', 0);
m.put('C', 1);
m.put('G', 2);
m.put('T', 3);
m.put('-', 4);
for(int i = 0; i < 4; i++) {
gene[i][i] = 5;
}
gene[1][0] = gene[0][1] = -1;
gene[2][0] = gene[0][2] = -2;
gene[2][1] = gene[1][2] = -3;
gene[3][0] = gene[0][3] = -1;
gene[3][1] = gene[1][3] = -2;
gene[3][2] = gene[2][3] = -2;
gene[4][0] = gene[0][4] = -3;
gene[4][1] = gene[1][4] = -4;
gene[4][2] = gene[2][4] = -2;
gene[4][3] = gene[3][4] = -1;
}
static void display(int len1, int len2) { //打印dp表,,可以任意改写,用于测试
for(int i = 0; i < len1; i++) {
for(int j = 0; j < len2; j++) {
System.out.print(dp[i][j] + " ");
}
System.out.println();
}
}
static void preprocess1(int len1, int len2) { //初始化memo表
for(int i = 0; i <= len1; i++) {
for(int j = 0; j <= len2; j++) {
memo[i][j] = -5;
}
}
}
static void preprocess2(int len1, int len2) { //初始化dp表
for(int i = 0; i <= len1; i++) {
for(int j = 0; j <= len2; j++) {
dp[i][j] = 0;
}
}
}
public static void main(String[] args) {
preprocess();
int t = sc.nextInt();
sc.nextLine();
while(t-->0) {
int len1 = sc.nextInt();
String str1 = sc.next();
int len2 = sc.nextInt();
String str2 = sc.next();
preprocess2(len1, len2);
dp(str1.toCharArray(), str2.toCharArray(), len1, len2);
//display(len1, len2);
}
}
}