矩阵乘法
状态表示为[i][j][k]表示这一个串中已经匹配好的有i个,差两步的有j个,差一步的有k个,显然i+j+k=len。
len最多11,所以状态数最多不到80
构造矩阵就是(i,j,k)->(i-1,j+1,k) ,有i个选择,要乘以i,另外两个转移也是一样的
然后就是一共能走几步的问题,统计一下最少步数复原要走几步,花费cost。能走的步数就是 复原的步数+3*((最多花费-花费)/走三步的花费)
然后矩阵乘法就可以了。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
using namespace std;
class ConversionMachine {
public:
int countAll(string, string, vector<int> , int);
};
long long pmod = 1000000007;
int id[12][12][12];
int rid[100][3];
int ed;
long long a[105][105], tmp[105][105], tr[105][105];
void mul(long long a[][105], long long b[][105]) {
int i, j, k;
memset(tmp, 0, sizeof(tmp));
for (i = 0; i < ed; ++i) {
for (j = 0; j < ed; ++j) {
for (k = 0; k < ed; ++k) {
tmp[i][j] += a[i][k] * b[k][j];
tmp[i][j] %= pmod;
}
}
}
for (i = 0; i < ed; ++i) {
for (j = 0; j < ed; ++j)
a[i][j] = tmp[i][j];
}
}
int ConversionMachine::countAll(string word1, string word2, vector<int> costs,
int maxCost) {
int i, j, k, n = word1.size();
int ii, jj, kk;
long long cost = 0;
int step = 0;
ii = jj = kk = 0;
for (i = 0; i < word1.size(); ++i) {
if (word1[i] == 'a') {
if (word2[i] == 'b') {
cost += costs[0];
step++;
kk++;
} else if (word2[i] == 'c') {
cost += costs[0] + costs[1];
step += 2;
jj++;
} else
ii++;
}
if (word1[i] == 'b') {
if (word2[i] == 'c') {
cost += costs[1];
step++;
kk++;
} else if (word2[i] == 'a') {
cost += costs[1] + costs[2];
step += 2;
jj++;
} else
ii++;
}
if (word1[i] == 'c') {
if (word2[i] == 'a') {
cost += costs[2];
step++;
kk++;
} else if (word2[i] == 'b') {
cost += costs[2] + costs[0];
step += 2;
jj++;
} else
ii++;
}
}
if (maxCost < cost)
return 0;
step += ((maxCost - cost) / (costs[0] + costs[1] + costs[2])) * 3;
ed = 0;
for (i = 0; i <= n; ++i) {
for (j = 0; i + j <= n; ++j) {
k = n - i - j;
id[i][j][k] = ed;
rid[ed][0] = i;
rid[ed][1] = j;
rid[ed][2] = k;
ed++;
}
}
memset(a, 0, sizeof(a));
ed++;
for (i = 0; i < ed; ++i)
a[i][i] = 1;
memset(tr, 0, sizeof(tr));
for (i = 0; i < ed - 1; ++i) {
int pi, pj, pk;
pi = rid[i][0];
pj = rid[i][1];
pk = rid[i][2];
if (pi > 0)
tr[i][id[pi - 1][pj + 1][pk]] += pi;
if (pj > 0)
tr[i][id[pi][pj - 1][pk + 1]] += pj;
if (pk > 0)
tr[i][id[pi + 1][pj][pk - 1]] += pk;
}
tr[ed - 1][ed - 1] = 1;
tr[ed - 1][id[ii][jj][kk]] = 1;
step++;
while (step) {
if (step & 1)
mul(a, tr);
mul(tr, tr);
step >>= 1;
}
return a[ed - 1][id[n][0][0]];
}