这里
0表示不操作,1表示异或自己,2表示异或邻居。。轮廓线dp
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pdd pair<double, double>
#define MP make_pair
#define fi first
#define se second
#define eps 1e-10
#define inf 0x3f3f3f3f
#define mod 1000000007
#define N 12
#define M 1500040
int n, m, tot, ans;
int dp[2][60050], st[M], id[M], code[N];
char s[N][N], ss[N][N];
void init(){
tot = 0;
int sta = 1 << (m * 2);
for(int i = 0; i < sta; ++i){
bool flag = 0;
for(int j = 0; j < m; ++j)
if((i >> (2 * j) & 3) == 3)
flag = 1;
if(!flag){
st[tot] = i;
id[i] = tot++;
}
}
}
void decode(int sta){
for(int i = 0; i < m; ++i)
code[i] = (sta >> (2 * i)) & 3;
}
int encode(){
int ret = 0;
for(int i = m - 1; i >= 0; --i)
ret = ret << 2 | code[i];
return id[ret];
}
void solve(){
memset(dp[0], 0x3f, sizeof dp[0]);
for(int i = 0; i < tot; ++i){
bool flag = 1;
for(int j = 0; j < m; ++j){
if((st[i] >> (j * 2) & 3) == 2)
flag = 0;
}
if(flag) dp[0][i] = 0;
}
int cur = 0, pre = 1;
for(int i = 0; i < n; ++i)
for(int j = 0; j < m; ++j){
cur ^= 1, pre ^= 1;
memset(dp[cur], 0x3f, sizeof dp[cur]);
for(int k = 0; k < tot; ++k){
int sta = k;
if(dp[pre][sta] == inf) continue;
decode(st[k]);
if(j == 0){
int up = code[j], nxt;
int tmp = i > 0 ? s[i-1][j] - '0' : 0;
if(up == 2){
code[j] = 0;
nxt = encode();
dp[cur][nxt] = min(dp[cur][nxt], dp[pre][sta] + 2);
code[j] = 1;
nxt = encode();
dp[cur][nxt] = min(dp[cur][nxt], dp[pre][sta]);
code[j] = 2;
nxt = encode();
dp[cur][nxt] = min(dp[cur][nxt], dp[pre][sta] + 1);
}
else {
if(tmp == up){
code[j] = 0; //不操作
nxt = encode();
dp[cur][nxt] = min(dp[cur][nxt], dp[pre][sta]);
code[j] = 1; //异或自己
nxt = encode();
dp[cur][nxt] = min(dp[cur][nxt], dp[pre][sta] + 2);
}
else{
code[j] = 2; //异或邻居
nxt = encode();
dp[cur][nxt] = min(dp[cur][nxt], dp[pre][sta] + 1);
}
}
continue;
}
int up = code[j], left = code[j-1], nxt;
int tmp = i > 0 ? s[i-1][j] - '0' : 0;
if(up == 2){
if(left == 2) code[j] = 1;
else code[j] = 0;
nxt = encode();
dp[cur][nxt] = min(dp[cur][nxt], dp[pre][sta] + 2);
if(left == 2) code[j] = 0;
else code[j] = 1;
nxt = encode();
dp[cur][nxt] = min(dp[cur][nxt], dp[pre][sta]);
code[j] = 2;
if(left < 2)
code[j-1] = left ^ 1;
nxt = encode();
dp[cur][nxt] = min(dp[cur][nxt], dp[pre][sta] + 1);
}
else{
if(up == tmp){
if(left == 2) code[j] = 1;
else code[j] = 0;
nxt = encode();
dp[cur][nxt] = min(dp[cur][nxt], dp[pre][sta]);
if(left == 2) code[j] = 0;
else code[j] = 1;
nxt = encode();
dp[cur][nxt] = min(dp[cur][nxt], dp[pre][sta] + 2);
}
else{
code[j] = 2;
if(left < 2)
code[j-1] = left ^ 1;
nxt = encode();
dp[cur][nxt] = min(dp[cur][nxt], dp[pre][sta] + 1);
}
}
}
}
ans = inf;
for(int i = 0; i < tot; ++i){
decode(st[i]);
bool flag = 1;
for(int j = 0; j < m; ++j){
if(code[j] == 2) continue;
int tmp = s[n-1][j] - '0';
if(tmp != code[j]) flag = 0;
}
if(flag)
ans = min(ans, dp[cur][i]);
}
}
int main(){
int kk = 0;
while(scanf("%d%d", &n, &m) != EOF){
if(n == 0 && m == 0) break;
for(int i = 0; i < n; ++i)
scanf("%s", s[i]);
if(n < m){
swap(n, m);
for(int i = 0; i < n; ++i)
for(int j = 0; j < m; ++j)
ss[i][j] = s[j][i];
for(int i = 0; i < n; ++i)
for(int j = 0; j < m; ++j)
s[i][j] = ss[i][j];
}
init();
solve();
printf("Case #%d: %d\n", ++kk, ans);
}
return 0;
}