在一个n*m的格子里面,有一些宝藏和一些聚集地;
‘.’ :表示空地,可以通过;
‘*’ :表示宝藏,可以通过;
‘#’ :表示墙,不能通过;
‘A’ ~ ‘Z’ || ‘a’ ~ ‘z’ :表示聚集地;
聚集地具有等级,就是他们的字典序;从最低字典序聚集地进入,从最高字典序聚集地出。且每次只能从一个聚集地出发去偷宝藏后要到其字典序后一个聚集地去,例如:A->x1->B->x2->C……同时是走最短路径。问最多能偷几个宝藏?
思路:
算出两个字典序之间的最短之间存不存在宝藏,有就连边,没就算了。
然后判断从最小字典序可不可以按顺序走到最高字典序;
对每个宝藏进行编号,如果某宝藏在两字典序的最短路之间;
k->x->k+1,那么就连接 <k,x> <script type="math/tex" id="MathJax-Element-8"> </script>;
对构成的图进行二分图匹配,最大匹配就是结果;
int dis[70][10010];
int d[70];
int mp[70][10010];
char s[101][101];
int n, m;
int ID(char c) {
if (c >= 'A' && c <= 'Z') return c - 'A';
return c - 'a' + 26;
}
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, -1, 0, 1};
void bfs(int x,int y,int id) {
queue<int> que;
que.push(x), que.push(y);
dis[id][x*m + y] = 0;
while(!que.empty()) {
x = que.front();que.pop();
y = que.front();que.pop();
for (int i = 0;i < 4;++i) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 0 && nx < n && ny >= 0 && ny < m && s[nx][ny] != '#' && dis[id][nx * m + ny] == -1) {
dis[id][nx*m + ny] = dis[id][x*m + y] + 1;
que.push(nx);que.push(ny);
// cout << s[nx][ny] << ' ';
if (isalpha(s[nx][ny]) && ID(s[nx][ny]) + 1 == id) {
d[ID(s[nx][ny])] = dis[id][x*m + y] + 1;
// bug;
}
}
}
}
// cout << endl;
}
int linker[10010];
bool vis[10010];
bool dfs(int u,int& p) {
for (int i = 0;i < p;++i) {
if (!vis[i] && mp[u][i]) {
vis[i] = true;
if (linker[i] == -1 || dfs(linker[i], p)) {
linker[i] = u;
return true;
}
}
}
return false;
}
int hungary(int& top, int& p) {
int ret = 0;
memset(linker, -1,sizeof linker);
for (int i = 0;i < top;++i) {
memset(vis, false,sizeof vis);
if (dfs(i, p)) ret++;
}
return ret;
}
int main(int argc, const char * argv[])
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
// clock_t _ = clock();
while(~scanf("%d%d", &n, &m)) {
for (int i = 0;i < n;++i)
scanf("%s", s[i]);
int top = 0;
memset(dis, -1,sizeof dis);
memset(d, -1,sizeof d);
for (int i = 0;i < n;++i) {
for (int j = 0;j < m;++j) {
if (isalpha(s[i][j])) {
top = max(top, ID(s[i][j]));
bfs(i, j, ID(s[i][j]));
}
}
}
bool ok = true;
// for (int i = 0;i < top;++i)
// cout << d[i] << ' ';
// cout << endl;
for (int i = 0;i < top;++i) {
if (d[i] == -1) {ok = false;break;}
}
if (!ok) {puts("-1");continue;}
int p = 0;
memset(mp, 0,sizeof mp);
for (int i = 0;i < n;++i) {
for (int j = 0;j < m;++j) {
if (s[i][j] == '*') {
for (int k = 0;k < top;++k) {
if (dis[k][i*m+j] + dis[k+1][i*m+j] == d[k])
mp[k][p] = 1;
}
p++;
}
}
}
cout << hungary(top, p) << endl;
}
// printf("\nTime cost: %.2fs\n", 1.0 * (clock() - _) / CLOCKS_PER_SEC);
return 0;
}