思路:
状压dp,用map写
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n"; const int N = ;
char s[N][N];
pii a[N];
int n, m, cnt, num[N];
LL p[N];
map<LL, int> dp[];
int main() {
p[] = ;
for (int i = ; i < N; ++i) p[i] = p[i-]*;
while(~scanf("%d %d", &n, &m)) {
if(!n && !m) break;
for (int i = ; i < n; ++i) scanf("%s", s[i]);
cnt = ;
for (int i = ; i < n; ++i) {
for (int j = ; j < m; ++j) {
if(isdigit(s[i][j])) {
a[cnt].fi = i;
a[cnt].se = j;
num[cnt] = s[i][j]-'';
++cnt;
}
}
}
dp[].clear(); dp[].clear();
int now = ;
dp[now][] = ;
int k;
for (int i = ; i < n; ++i) {
for (int j = ; j < m; ++j) {
now ^= ;
dp[now].clear();
for (auto t : dp[now^]) {
LL x = t.fi;
for (k = ; k < cnt; ++k) {
if((x/p[k])% != num[k] && (i*m+j)-(a[k].fi*m+a[k].se) >= m+) break;
}
if(k < cnt) continue;
if(dp[now].find(x) == dp[now].end()) dp[now][x] = t.se;
else dp[now][x] = min(dp[now][x], t.se);
if(s[i][j] == '.') continue;
for (k = ; k < cnt; ++k) {
if(i- <= a[k].fi && a[k].fi <= i+ && j- <= a[k].se && a[k].se <= j+) {
if((x/p[k])% == num[k]) break;
x += p[k];
}
}
if(k < cnt) continue;
if(dp[now].find(x) == dp[now].end()) dp[now][x] = t.se + ;
else dp[now][x] = min(dp[now][x], t.se + );
}
}
}
LL x = ;
for (int i = ; i < cnt; ++i) x += num[i]*p[i];
printf("%d\n", dp[now][x]);
}
return ;
}