P4059 [Code+#1]找爸爸


我们不妨设

\[f[i][j][k]表示A串匹配到了i位,B串匹配到了j位,匹配到这种情况的加空格情况为k \]

发现加空格的无非就这四种情况
1.A加B加(都加空格,相似值肯定会降低,对匹配也没有贡献。所以可以排除)
2.A加B不加
3.A加B加
4.A,B都不加

那么我们令k=0表示为都不加,k=1表示A后面加,k=1表示B后面加。
若要表示末尾连续加空格的情况,则要先预处理出来。

那么状态转移方程就不难得到了。。

#include
#define rep(i,j,k) for(register int i(j);i<=k;++i)
#define drp(i,j,k) for(register int i(j);i>=k;--i)
#define int long long
using namespace std;
typedef long long lxl;
template
inline T  max(T a, T b, T c) {
	return max(max(a, b), c);
}
template
inline T  min(T &a, T &b) {
	return a < b ? a : b;
}
const int N = 3e3 + 79;
int f[N][N][3];
inline int M(char c) {
	if(c == 'A') return 1;
	if(c == 'T') return 2;
	if(c == 'C') return 4;
	if(c == 'G') return 3;
}//ATCG写惯了+不认真读题,WA++

char cb[N], ca[N];
int a[N], b[N], A, B;
int m, n;
int d[5][5];

 main() {
	ios::sync_with_stdio(false);
	cin >> (ca + 1);
	cin >> (cb + 1);
	n = strlen(ca + 1);
	m = strlen(cb + 1);

	rep(i, 1, n) {
		a[i] = M(ca[i]);
	}
	rep(j, 1, m) {
		b[j] = M(cb[j]);
	}
	rep(i, 1, 4)
	rep(j, 1, 4)
	cin >> d[i][j];
	
	cin >> A >> B;

	rep(i, 1, max(n, m)) {
		f[0][i][1] = f[i][0][2] = -A - B * (i - 1);
		f[0][i][0] = f[i][0][0] = -(1LL << 60);//都不加空格,但是没有匹配上,不是有解的
		f[i][0][1]=f[0][i][2]=-(1LL << 60);//状态表示不正确,不合法状态
	}


	f[0][0][1] = f[0][0][2] =-(1LL << 60);
	
	rep(i, 1, n)
	rep(j, 1, m) {
		f[i][j][0] = max(f[i - 1][j - 1][0], f[i - 1][j - 1][1], f[i - 1][j - 1][2]) + d[a[i]][b[j]] ; //2??ó?????¥??é?
		f[i][j][1] = max(f[i][j - 1][1] - B, f[i][j - 1][0] - A, f[i][j - 1][2] - A);
		f[i][j][2] = max(f[i - 1][j][2] - B, f[i - 1][j][0] - A, f[i - 1][j][1] - A);
	}
	cout << max(f[n][m][0], f[n][m][1], f[n][m][2]) << '\n';
	return 0;
}

相关